Trouble understanding one line in Insertion Sort (Python 3) - arrays

I was looking through the other threads concerning the Insertion Sort but didn't find the answer that relates to the specific part of it which I do not understand.
My full Insertion Sort algorithm can be seen below. It works as intended, but I cannot figure out the purpose of that last line.
array[position] = value
Let me explain through an example:
When the 'for' loop starts, index = 1.
=> value = array[1] = 3
=> position = 1
=> Since 4 > 3, the item at index 1, is swapped with the item at index 0.
=> position -= 1
=> position = 0
We now get to the line which confuses me:
array[0] = value
=> value = array[index] = array[0] = 3
However, when the 'for' loop goes through its second iteration, index = 2.
And so immediately value = array[2] and position = 2 ?
Even though I know that this last line of code is necessary I just cannot see what purpose it serves.
Could someone please explain to me this final logical step?
Thank you in advance for your time and help.
array = [4,3,5,6,12,9,8,6]
for index in range (1, len(array)):
value = array[index]
position = index
while position > 0 and array[position - 1] > value:
array[position] = array[position - 1]
position -= 1
array[position] = value

The position variable represents (at the end) where you will eventually insert the number. Without the last line, you are not inserting the number at 'position' at the correct place (it will result in the 1 index after). Below is my code for insertion sort.
def insertionSort(arr):
length = len(arr)
for i in range(1, length):
currNum = arr[i]
j = i - 1
while j >= 0 and currNum < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j+1] = currNum
return arr

You wouldn't have really swapped the numbers without that line, would you?
index 1:
-> [4,3,5,6,12,9,8,6] (enters while loop)
-> [4,4,5,6,12,9,8,6] ("pushes" 4 to position 1)
-> <waits for while loop to finish>
-> [3,4,5,6,12,9,8,6] (assigns 3 to position 0 since there are no other elements > 3)
index 2:
...

I think is not really needed at start in for loop, because it was used to index inside the loop. Looks the picture

Related

Next greater element over a certain percentage of each element in array

I have seen some posts about next greater element. I am looking for a more performant solution for one of its variant.
The problem :
I have an array of numbers. I want to know for each number, the next index where the value become bigger than a percentage of X.
Example :
Let's suppose I have this array [1000, 900, 1005, 1022, 1006] and I set a target of 1%. Meanwhile, I want to know when the value become 1% bigger than it was.
1000 -> We want to know when value become bigger of equal to 1010 -> Index = 3
900 -> We want to know when value become bigger of equal to 909 -> Index = 2
1005 -> We want to know when value become bigger of equal to 1015.05 -> Index = 3
1022 -> We want to know when value become bigger of equal to 1030.2 -> Index = -1
1006 -> We want to know when value become bigger of equal to 1016.06 -> Index = -1
Naïve solution :
An O(n^2) algorithm can solve the problem. But it's too slow for my needs.
Does anyone know a faster algorithm to solve this problem or one of its close variant ?
I'd use a min heap. Each element in the min heap is a tuple (value, index) where value is the target value, and index is the index in the input array where that target value originated.
Then the algorithm is:
create an output array with all elements set to -1
for each element in the input array
for each target value on the min heap less than the element's value
pop the (targetValue, targetIndex) tuple
record the index of the current input element at the target index
add the current element (value, index) tuple to the min heap
For example, given the array in the question, the algorithm performs the following steps:
Create an output array with all elements set to -1
Read 1000, put (1010, 0) in the min heap.
Read 900, put (909, 1) in the min heap.
Read 1005. That's larger than 909, so pop the (909, 1), and record index 2 as the answer for element 909. Put (1015.05, 2) in the min heap.
Read 1022. Pop (1010, 0) and then (1015.05, 2) from the min heap, recording index 3 as the answer for elements 1000 and 1005. Put (1030.2, 3) in the min heap.
Read 1006, put (1016.06, 4) in the min heap.
Since the end of the input array has been reached, (1030.2, 3) and (1016.06, 4) will never be popped, and the corresponding elements in the output array remain as -1
Running time is O(nlogn).
Sample python implementation:
from heapq import heappush, heappop
def nextGreater(inputArray):
targetHeap = []
outputArray = [-1] * len(inputArray)
for inputIndex, inputValue in enumerate(inputArray):
while targetHeap and targetHeap[0][0] < inputValue:
targetValue, targetIndex = heappop(targetHeap)
outputArray[targetIndex] = inputIndex
heappush(targetHeap, (inputValue * 1.01, inputIndex))
return outputArray
inputArray = [1000, 900, 1005, 1022, 1006]
outputArray = nextGreater(inputArray)
print outputArray # [3, 2, 3, -1, -1]
You can create a list of tuples of index and value in array. Sort the list by value. Then you can iterate over the list using two pointers finding values that are greater by the given percentage and capture the corresponding indices. Complexity would be O(nlogn)
Sample implementation in java 17 given below:
final double percentage = 1.01;
int[] arr = new int[]{1000, 900, 1005, 1022, 1006};
record KeyValuePair(int value, int index) {}
List<KeyValuePair> keyValuePairs = new ArrayList<>();
for (int i = 0; i < arr.length; ++i) {
keyValuePairs.add(new KeyValuePair(arr[i], i));
}
keyValuePairs.sort(Comparator.comparingInt(KeyValuePair::value));
int i = 0, j = 1;
while (i != keyValuePairs.size() && j != keyValuePairs.size()) {
if (keyValuePairs.get(i).value() * percentage < keyValuePairs.get(j).value()) {
if (keyValuePairs.get(i).index() < keyValuePairs.get(j).index()) {
System.out.println("For index " + keyValuePairs.get(i).index() + " -> " + keyValuePairs.get(j).index());
} else if (keyValuePairs.get(i).index() + 1 != keyValuePairs.size()) {
System.out.println("For index " + keyValuePairs.get(i).index() + " -> " + (keyValuePairs.get(i).index() + 1));
}
++i;
} else {
++j;
}
}

Find all ascending triplets in array

I'm trying to exctract all the ascending triplets in an array of arbitrary dimension. For example if i have an array like [1 2 3 4] i'd like to obtain [1 2 3] , [1 2 4] , [2 3 4]
Here's a simple "graphical" example with 5 elements:
The arrows are the indexes used to iterate, each step is a found triplet.
So far i've just implemented a simple sorting algorithm, which will give me the ordered array.
Once i have the ordered array, I iterate with 3 possible pointers (or just indexes) increasing the pointer starting at the third element until it reaches the end of the array.
Once it reaches the end, i'll increase the second pointer and reset the third to the position right next to the pointer 2 and so on.
array = [ 3 2 1 5 ];
array = sort(array);
//Now i should iterate over the 3 indexes, but i'm totally lost about how to place them
for i=1:length(array-2)
for j=2:length(array-1)
for k=3:length(array)
//storing triplet
end
end
end
Right now i'm able to iterate over the array, and i can extract all the triplets until the k index reaches the end of the array.
The problem is once i reach for the end, i have to increment the j index starting point and reset the k index to be right next to the second index.
To make it clear: right now once k reaches the end, it will start again from 3 and j will also be 3, but i need them to be j = 3 and k = 4 after the first iteration of k is completed and so on (this is valid also for j compared to i , look at the image for a clearer explanation).
How do i fix the indexes in order to extract the triplets correctly?
Seems to me like your inner iterations start one after your outer one:
for j=(i+1):length(array-1)
for k=(j+1):length(array-1)
Generalizing the first loop to the rest.
const arrayTotal = [3, 2, 1, 5];
let combinationArray = [];
arrayTotal.sort();
for (let i = 0; i < (arrayTotal.length - 2); i++) {
for (let j = (i + 1); j < (arrayTotal.length - 1); j++) {
for (let k = (j + 1); k < arrayTotal.length; k++) {
combinationArray.push([arrayTotal[i], arrayTotal[j], arrayTotal[k]])
}
}
}
console.log(combinationArray);

adjacentElementsProduct function in ruby

I'm stuck on an algorithm for a function called adjacentElementsProduct that accepts an array as the argument. It's supposed to return the largest product of adjacent numbers in the array. For example, if the argument is [2,4,1,3,2,6] it would return 12 because of the pair of 2 and 6.
my code is
def adjacentElementsProduct(inputArray)
idx1 = 0
idx2 = 1
while idx2 < inputArray.length
pair = [inputArray[idx1], inputArray[idx1 + 1]]
next_pair = [inputArray[idx2], inputArray[idx2 + 1]]
if next_pair.reduce(:+) > pair.reduce(:+)
pair = next_pair
idx1 += 1
idx2 += 1
else
idx1 += 1
idx2 += 1
end
end
pair.reduce(:+)
end
I just can't figure out where my code is not working. I'm just looking for a push in the right direction because I know just being given the answer won't help me as much. Can anyone help me?
The code makes no sense :).
You are using + instead of *
And in the loop you always assign pair = [inputArray[idx1], inputArray[idx1 + 1]].
So you always return the last pair or the previous. If the maximum product is at the beginning, you still keep advancing the pair variable until the end of the loop.
Besides, the solution is quite complicated.
def adjacentElementsProduct(inputArray)
index = 0
length = inputArray.length
max = 0
while index < length-1 do
result = inputArray[index] * inputArray[index+1]
max = result if result > max
index += 1
end
max
end

A simple sorting algorithm

This is a simple sorting function that I wrote in Matlab:
function [matrix] = sorting(matrix)
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
check_sorted(matrix)
end
function [matrix] = check_sorted(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
if count+1 < length(matrix)
sorting(matrix);
end
end
The input for sorting function is a 1D array, e.g. [4 3 2 1], and it successfully returns the sorted array [1 2 3 4] for the first time I call it, but then it starts to return unsorted arrays?
You've got a missing semicolon that is causing the results of each call to check_sorted to be displayed, which is confusing things. If you add the semicolon, the output from sorting with the array [2 4 1 3] suggested in the comments is:
>> sorting([2 4 1 3])
ans =
2 1 3 4
Clearly this isn't sorted. The problem is that MATLAB passes function arguments by value, not by reference. Since you're not returning the re-sorted matrix from check_sorted or updating the return matrix in sorting the original matrix never gets updated. You need to change at least one line in each function (changed lines are commented):
function [matrix] = check_sorted(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
if count+1 < length(matrix)
matrix = sorting(matrix); % change: return re-sorted matrix
end
end
function [matrix] = sorting(matrix)
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
matrix = check_sorted(matrix); % change: return checked matrix
end
Now the matrix will be updated if it is not sorted on the first (or any subsequent) pass and the fully sorted matrix will be returned by sorting.
This is an odd sort of recursion that really isn't necessary. If you change check_sorted to return a boolean value, true for sorted, false for not sorted, you can change that recursion to a while loop around the for loop in sorting:
function [TF] = check_sorted2(matrix)
count = 0;
for index = 1:length(matrix)-1
if matrix(index) < matrix(index + 1)
count = count + 1;
end
end
TF = count+1 == length(matrix); % TF = true if matrix is sorted
% TF = false otherwise
end
function [matrix] = sorting2(matrix)
while ~check_sorted2(matrix) % keep going until matrix is sorted
for index = 1:length(matrix)-1
if matrix(index) > matrix(index + 1)
temp = matrix(index + 1);
matrix(index + 1) = matrix(index);
matrix(index) = temp;
end
end
end
end
Of course the whole thing can be optimized and vectorized, but this will at least get you going.
i tested your algorithms and it worked. so something else might be wrong. but this algorithm is very very inefficient. you may google sort and pick one that suits you.
if you really want to stick with the algorithm, you could improve it by shortening the two loops. for example, after first call to sorting, for each subsequent call to sorting, you could shorten the loop cycle by 1 because the first call to sorting would put the largest number to the end of the array, the second call would put the second largest to the second from the end, and so on. this is so called bubble sorting. also in check_sorted, you don't need to go through the entire length of the array to check if the array has been sorted. as soon as you see matrix(index) > matrix(index + 1), you can immediately exit the loop (after you set a flag to indicate the array hasn't been sorted).

MATLAB: Finding the entry number of the first '1' in a logical array

I have created a logical array of 1's and 0's using the following code:
nWindow = 10;
LowerTotInitial = std(LowerTot(1:nWindow));
UpperTotInitial = std(UpperTot(1:nWindow));
flag = 0;
flagArray = zeros(length(LowerTot), 1);
for n = 1 : nData0 - nWindow
for k = 0 : nWindow - 1
if LowerTot(n + k) < 0.1*LowerTotInitial || UpperTot(n + k) < 0.1*UpperTotInitial
flag = 1;
flagArray(n) = 1;
else
flag = 0;
end
end
end
This returns flagArray, an array of 0's and 1's. I am trying to find the index of the first 1 in the array. ie. 1 = flagArray(index). I am confused as to what is the best way to accomplish this!
What you call an entry number is referred to as an index in MATLAB-speak. To find the index of the first matching element in an array you can use the FIND function:
>> x = [0 0 1 0 1 0];
>> find(x, 1, 'first')
ans =
3
Try this ind = find(flagArray, k, 'first')
with k =1
Read this Matlab Docs - find

Resources