function insertionSort(arr) {
var length = arr.length,
val,
i,
j;
for(i = 0; i < length; i++) {
value = arr[i];
for(j = i - 1; j > -1 && arr[j] > value; j--) {
arr[j+1] = arr[j]
}
arr[j+1] = value;
}
return arr;
}
console.log(insertionSort([6,1,23,4,2,3]))
I am looking at an example of the insertion sort algorithm encoded in javascript, and having trouble understanding why it passes the conditional of the inner for loop. To be clear, this algorithm is correct -- I'm just having difficulty understanding why.
If j is initialized with i - 1, then the value of j is -1, since i is initialized at 0. In the first part of the conditional it states j > -1, which means it won't pass the this test, since j is not greater than -1.
Can someone tell me what I am missing?
You're right, the first iteration will not enter the second loop, but this is okay. Notice what that loop is doing. It's swapping array[j+1] with array[j]. When i == 0, then j == -1. You can't swap array[0] with array[-1], since it doesn't exist. This is a clever way of bypassing that issue.
However, this only happens on the first iteration. Subsequent iterations will enter the loop as expected.
Related
I don't understand why this piece of code doesn't work:
let i = 0;
let arr = [];
while(i < 8){
arr[i] = i;
i++;
}
for(i = 0; arr[i]; i++) {
console.log("Result:", arr[i]);
}
I want to log each element of the array while the condition is true
I know that i equals to 8 after the while loop, but even an "i=0" before the for doesn't solve the issue (BTW why the i = 0 inside the for initialisation doesn't set it to 0?)
Can someone explain me what breaks the code?
for loops run until the condition is not true.
The first time around the loop i is 0 so arr[i] is arr[0] which you've populated with a 0.
0 is a false value, so the condition is false and the loop ends before the first iteration.
You probably want the condition to be i < arr.length.
In your first look you set arr[i] = i. In the second loop your condition is arr[i], and on the first iteration i = 0, which means arr[i] is 0 which evaluates to false causing your loop to exit.
i am trying to figure out how this code works.
function Kth_greatest_in_array(arr, k) {
for (let i = 0; i < k; i++) {
let max_index = i;
const tmp = arr[i];
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] > arr[max_index]) {
max_index = j;
}
}
arr[i] = arr[max_index];
arr[max_index] = tmp;
}
return arr[k - 1];
}
console.log(Kth_greatest_in_array([1,2,6,4,5], 3))
As you can see the goal is to find third biggest value. But i don know how the second loop works. Could you explain it to me step by step. For example, what is the meaning of veriable j, especially why they typed let j = i +
This method basically performs an in-place sort of the arr array (but only "k" times - not a full sort), then returns the element (from the now partially sorted array) at index k-1.
The inner for loop looks through the remaining (unsorted) portion of the array to find the index of the item with the highest value:
if (arr[j] > arr[max_index]) {
max_index = j;
}
The specific statement you were asking about, let j = i + 1, means "declare a new variable, j, and set its initial value to one greater than the current iteration of the outer for loop". "j" is arbitrary and could be any valid identifier, it's just often used by convention when you have nested for loops since the outermost loop usually uses i (which is presumably short for "index").
At the end of each iteration of the outer for loop, these lines swap array elements so that this element is in the correct position:
arr[i] = arr[max_index];
arr[max_index] = tmp;
If you're curious to really understand the inner workings of a method like this, I'd highly encourage you to step through it with a debugger - it can be a great learning experience. Even just the tried-and-true method of sprinkling some temporary console.log statements can help illuminate what's going on (e.g., print the state of arr and max_index after every outer and inner loop iteration).
I've got working code, but I'm looking to improve the way I understand and implement different coding techniques as a whole. I thought this problem presented a good chance to get feedback on what I'm doing.
The idea here is to take two arguments, an array and an integer. Identify all pairs in the array that sum to make the integer argument, and then return the sum of the indices. You cannot reuse an index, and you must always use the smallest index available to you. There is an explanation on the FCC code guide here: https://www.freecodecamp.org/learn/coding-interview-prep/algorithms/pairwise
So - here is the question. Is there any good way of doing this without using nested for loops? I am becoming increasingly aware of time/space complexities, and I know that O(n^2) won't land me the job.
I would imagine a hashmap of some sort would come into it, but I just don't have the experience and knowledge to know how to use them.
Here is the code:
function pairwise(arr, arg) {
let usedIndex = [];
let output = 0;
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (
arr[i] + arr[j] == arg
&& usedIndex.indexOf(i) == -1
&& usedIndex.indexOf(j) == -1
) {
usedIndex.push(i, j)
output += i + j
}
}
}
return output;
}
pairwise([0, 0, 0, 0, 1, 1], 1) // should return 10
This can be done in one loop with some clever use of an object and knowledge that indices can only be used once.
function pairwise(arr, arg) {
let map = {};
let output = 0;
let length = arr.length;
for (let i = 0; i < length; i++) {
let subArr = map[arr[i]];
if(subArr && subArr[0] !== undefined) {
//there is an index waiting to pair, remove it and add to output
output += subArr.pop() + i;
} else {
//add this index to its pair slot
let left = arg - arr[i];
if(!map[left]) map[left] = [];
map[left].unshift(i);
}
}
return output;
}
console.log(pairwise([0, 0, 0, 0, 1, 1], 1), "should be 10");
console.log(pairwise([1, 4, 2, 3, 0, 5], 7), "should be 11");
console.log(pairwise([], 100), "should be 0");
console.log(pairwise([1, 3, 2, 4], 4), "should be 1");
The keys of the map represent the other value needed to make a pair, and the values of the map are arrays of indices that have the value that would make a pair. The indices are inserted using unshift() so that pop() returns the first one that was inserted - the smallest one.
Iterating from the front guarantees that the smallest pairs are found first, and the map guarantees that any later index will know exactly what the earliest index that could make a pair is.
For a better performance you can save the arr.length into a variable, then for loop won't count every single loop.
function pairwise(arr, arg) {
let usedIndex = [];
let output = 0;
let length = arr.length;
for (let i = 0; i < length; i++) {
for (let j = i + 1; j < length; j++) {
if (
arr[i] + arr[j] == arg
&& usedIndex.indexOf(i) == -1
&& usedIndex.indexOf(j) == -1
) {
usedIndex.push(i, j)
output += i + j
}
}
}
return output;
}
Sort the list.
Have two counters walking from the ends. At each step check to see if the sum is what you want. If so, capture the desired metric.
Step 1 is O(n*logn).
Step 2 is O(n) -- each counter will go about halfway through the list, stopping when they meet.
Recently I stole some javascript to select an option in a select element:
var el=document.getElementById('mySelect');
var opts=el.options;
for (var opt, j = 0; opt = opts[j]; j++) {
if (opt.value == 'Apple') {
el.selectedIndex = j;
break;
}
}
It works fine, but as I looked at it I realized it was different from what I would have written:
var el=document.getElementById('mySelect');
for (var j = 0; j < el.options.length; j++) {
if (el.options[j].value == 'Apple') {
el.selectedIndex = j;
break;
}
}
In looking at the first code, what stops the loop if 'Apple' is not found? Which one is 'better'?
In either case, the second expression determines if the loop should continue or stop. In yours,
for (var j = 0; j < el.options.length; j++) {}
it's straightforward, j will increment and as long as j is less than the options length it's true, and at some point it is equal to the length and then it stops. In the other one,
for (var opt, j = 0; opt = opts[j]; j++) {}
the difference is that they are declaring a variable opt and in the second expression set it to the (also incrementing) array index. At some point, j goes beyond the bounds of the array, and opts[j] is undefined. And since an equality expression in JS is the value of the right site, that expression is also undefined, which is falsy, and the loop stops.
As for which is better? Both work. But as you had to scratch your head and wonder about one of them, how much do you want to depend on code that's more difficult to read?
Long story short:
In your for loop var opt is executed once after which you have subsequent opt = data[i].
This is important because:
var opt, data = [1, 2]; // defined once
console.log(opt = data[0]) // 1
console.log(opt = data[1]) // 2
console.log(opt = data[2]) // undefined
When the for loop condition evaluates to falsy it will halt.
So in your case it does stop when opt = data[i] ends up being a falsy value - undefined
Which is at the point of i being 5 and data[i] becoming undefined and being assigned to opt ... which returns as a final result undefined.
You should also consider using this (if ES6 is an option):
var el=document.getElementById('mySelect');
el.selectedIndex = el.options.findIndex(x => x.value === 'Apple')
It is shorted and easier to read :).
Hi I have an array that looks like:
hrarray = [-9,-7,0,3,7,8]
I've been trying to work out a function that selects the first non-negative (inc. 0) number in the array and returns the index (var elemid):
for (var i = 0, len=hrArray.length; i<len; i++) {
var num = hrArray[i];
if(num > 0) {
var elemid = i; //returns first non-negative element index
}
else if(num < 0) {}
Is my code logic correct?
I don't see you returning anything.
You can get the first non-negative with a single line:
for (var i = 0, len = arr.length; i < len && arr[i] < 0; i++);
Basically, we place the check for negatives in the for-loop guard. It will break once it finds a non-negative and hence return i of that first non-negative.
Update #1 (to use in a function):
function getFirstNonNegative(arr) {
for (var i = 0, len = arr.length; i < len && arr[i] < 0; i++);
// Use a ternary operator
return (i === len) ? -1 : i; // If i === len then the entire array is negative
}
Your code will assign to elemid the last non-negative in the array. Try this:
var elemid=-1; // elemid should be declared outside the for statement
for (var i = 0, len=hrArray.length; i<len; i++) {
if(hrArray[i] > 0) {
elemid = i; //returns first non-negative element index
break;
}
}
The main problem I see is that you're not breaking out of the loop once you find a non-negative value. This can be done with a break statement, or if you want to exit a function immediately, a return statement.
The function should look a bit like this:
function findNonNegative(arry) {
for (var i = 0, len = arry.length; i < len; i++) {
if(arry[i] >= 0)
return i;
}
return -1;
}
Note that this method returns -1 if no non-negative elements are found.
And with a little tweaking, this can be shortened to:
function findNonNegative(arry) {
for (var i = 0; arry[i] < 0; i++);
return i < arry.length ? i : -1;
}
This version takes advantage of the behavior of the for loop to both test our values inside the loop and break out once a desired value is found. It also depends on the fact that x < y always returns false if x is undefined, thus ensuring we do not end up with an infinite loop. The last conditional expression is there to make the return value equal -1 if no non-negative elements were found; that can be reduced to just return i; if you are okay with the return value being arry.length in that case.