var levelOrder = function(root) {
const arr = [];
function traverse(node, level) {
if (!node) return;
if(arr[level] === undefined) {
arr[level] = [];
arr[level].push(node.val)
} else {
arr[level].push(node.val)
}
traverse(node.left, level + 1);
traverse(node.right, level + 1);
}
traverse(root, 0);
return arr;
};
In the recursion call to traverse function. Using
traverse(node.left, level + 1);
gives me the correct answer but
traverse(node.left, ++level);
gives me incorrect answer.
Let's say level is currently 0. My hypothesis is that the first example will feed 1 as the second argument to the traverse function. Second example will assign 1 to level (level = level + 1) and feed level(which is 1) as the second argument to the traverse function.
Lets assume level = 5;
level + 1 is an expression that returns the value 6 and doesn't change the value of level at all, so its value is still 5.
++level is an expression that increments that value of level to 6 and then returns the value of level which is now 6.
Twice in a row like in your function:
level + 1; // returns 6
level + 1; // returns 6
And now the other way:
++level; // returns 6
++level; // returns 7
That's why it's failing.
Related
Please consider this snippet of code:
var i = 1;
i = i-- + ++i;
My understanding of the order in which the operators & operands are processed is as follows:
i is incremented by 1 (pre-fix increment)
i is added to i( addition )
i is decremented by 1(post-fix decrement)
The value of the right hand side is assigned to i (assignment operation)
If my understanding is correct, i should end up having a value of 3. However, I printed out the result using some online javascript interpreter, and the end value of i is 2.
Where did I get wrong?
var i = 1;
i = i-- + ++i;
this is how the compiler will go about working through this code
create a variable called i
set the value of i to 1
(rhs first element) take value of i (1) decrement value (i is now 0)
(rhs second element) increment value of i (i is now 1)
set the value of i to rhs (2)
JavaScript always evaluates subexpressions in a left-to-right order, and then applies the operator:
// parentheses added for clarity
i = (i--) + (++i); // i = 1
i = 1 + (++i); // i = 0 after i--
i = 1 + 1 ; // i = 1 after ++i
i = 2 ;
Understanding the logic with precedence values:
var i = 1;
i = i-- + ++i;
prefix increment(++i) precedence = 17
postfix decrement(i--) precedence = 16
addition(+) precedence = 14
i = 1 + 1
i = 2
More precedence related info can be found in,
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
I want to visually understand what happens when this recursive code is run. I don't understand how the end result is 9.
In my mind, the f(x - 1) will iterate until it returns 5, then you add 1 which equals 6.
let f = x => {
if (x === 0) {
return 5
}
return 1 + f(x - 1)
}
let y = f(4)
console.log(y)
Thank you for your time
You have the reasoning backwards. It isn't that one gets added once at the very end, one gets added after each resursive call returns. Think about this line:
return 1 + f(x - 1)
Once the recursive f call returns, one is added to that result. Then this recursive call returns, and one is added again. That keeps happening until the initial call returns.
Since one is added once per recursive call, and it will recurse four times, and the base case returns 5, this function ends up basically just calculating
1 + 1 + 1 + 1 + 5 == 9
You could take a level for an indention of a log and look which level has an input and return value.
function f(x, level = 0) {
console.log(level, '>>'.repeat(level + 1), x);
var v = x === 0
? 5
: 1 + f(x - 1, level + 1);
console.log(level, '<<'.repeat(level + 1), v);
return v;
}
console.log('result', f(4));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm doing a kata on Codewars. I'm supposed to write a function that returns the index of which number, is not like the others, in evenness(i.e. [1, 2, 4] should return 0). I believe I have a solution, and it proves true when copy/pasting the code, and console.logging on freecodecamps live server, however, when i try to run the code where it is written, it only passes one test. What is going wrong here?
I've tried testing with console.logs, and my solution holds. I know I could just use filter to solve the problem, but i wan't to practice fundamentals.
let odd = [];
let even = [];
function isEven(num) {
if (num % 2 === 0) {
return true;
} else {
return false;
}
}
function iqTest(numbers) {
let nums = numbers.split(' ').map(function(item) {
return parseInt(item, 10);
})
for (let i in nums) {
if (isEven(nums[i])) {
even.push(nums[i])
} else {
odd.push(nums[i])
}
}
if (even.length > odd.length) {
return nums.indexOf(odd[0]) + 1;
} else {
return nums.indexOf(even[0]) + 1;
}
}
The function should accept a string of numbers, one of which will not be either even or odd, then return the index of that number + 1.
You could take the in comments mentioned approach and search for at least one odd and one even and one additional item, at least three items and exit early if this combination is found.
No need to convert the values in advance, because the value get converted to number by using the remainder operator of isEven function.
For a faster return value store the index instead of the value and omit a later indexOf seach.
function isEven(i) { return i % 2 === 0; }
function iqTest(numbers) {
var even = [], odd = [], values = numbers.split(' ');
for (let i = 0; i < values.length; i++) {
(isEven(values[i]) ? even : odd).push(i);
if (even.length && odd.length && even.length + odd.length > 2)
return (even.length < odd.length ? even : odd)[0] + 1;
}
}
console.log(iqTest("1 2 4")); // 1
console.log(iqTest("2 4 7 8 10")) // 3
console.log(iqTest("1 2 1 1")); // 2
I have what I think surely is a really simple question for most of you. But I have some trouble to get my head around this for loop. What does the -1 in argument.length -1 stand for? Is it the last item? And the i-- that is for decrease by 1?
var plus = function() {
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2,2,3,657,5643,4465,2,45,6));
When you call arguments.length It will return you the number of elements with the last one accessed with arguments[arguments.length-1] because counting starts with 0.
(the First element is accessed like this arguments[0]).
Here is good documentation for Java but it is the same for JavaScript: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
And yes i-- decreases i for 1. It is different i-- and --i.
Using ++/-- After the Operand
When you use the increment/decrement operator after the operand, the value will be returned before the operand is increased/decreased.
Check out this example:
// Increment
let a = 1;
console.log(a++); // 1
console.log(a); // 2
// Decrement
let b = 1;
console.log(b--); // 1
console.log(b); // 0
When we first log out the value of a, or b, neither has changed. That’s because the original value of the operand is being returned prior to the operand being changed. The next time the operator is used, we get the result of the +1, or -1.
Using ++/-- Before the Operand
If you’d rather make the variable increment/decrement before returning, you simply have to use the increment/decrement operator before the operand:
// Increment
let a = 1;
console.log(++a); // 2
console.log(a); // 2
// Decrement
let b = 1;
console.log(--b); // 0
console.log(b); // 0
As you can see in the above example, but using ++ or -- prior to our variable, the operation executes and adds/subtracts 1 prior to returning. This allows us to instantly log out and see the resulting value.
The - 1 means to subtract 1 from arguments.length. i-- means to decrease i by 1.
You need to know two things here:
arguments is a object type so it has key-value pair of values you passed as a argument into a function. Furthermore, the arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length.
The key of arguments always starts with 0 and ends with one value less than the length of arguments. See the example below the key ends at 8 so you do arguments.length - 1 so that you get 8 instead of 9.
And since you are looping considering the last value first in arguments you do --i.
var plus = function() {
console.log(arguments);
console.log(typeof arguments);
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
Alternatively, you can also do i++ as,
var plus = function() {
var sum = 0;
for (var i = 0; i <arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
I'm trying to understand the following recursive function below to teach myself recursion. My attempt to explain it is below the expected output and the function itself. what am I missing? I'm not seeing the process where you get from 'abc' to 'acb'. my attempt to understand it got me from 'abc' right to 'bac'.
example usage:
var anagrams = allAnagrams('abc');
console.log(anagrams); // [ 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' ]
var allAnagrams = function(string) {
var uniqueOutput = {};
(function anagram(ana, str) {
// could have also written this as: if(!str)....
if (str === '') {
uniqueOutput[ana] = 1;
}
//recursive call for the length of the anagram.
for (var i = 0; i < str.length; i++) {
anagram(ana + str[i], str.slice(0, i) + str.slice(i + 1));
console.log(ana);
}
})('', string);
console.log(uniqueOutput)
return Object.keys(uniqueOutput);
};
// you are calling the recursive function like this: anagram([anagram=]'', [string=]'abc')
// so the base case is not met on the first iteration since the string isn't empty
// first iteration: i = 0
// anagram('' + 'a' + 'bc' [from str.slice(0 +1)]) ---> resolves to "abc") ---> anagram("abc")
//second iteration: i = 1. we are still in the original call from line 37.
// here below, does "ana" stay as '' since we are still inside the initial recursion call?
//anagram('' + b + a + c) ---- resolves to "bac" ---> anagram("bac")
//third and last iteration iteration: i = 2
//anagram(" " + c + c) ----> anagram("cc") ? not a valid result.
My new, correct (I think) explanation:
//initial input: anagram("", "abc")
//STEP 1: enter the function --> i = 0 for original string "abc"
//anagram("" + "a", "bc") ----> anagram("a", "bc")
//STEP 2: loop through the new, modified string, which is now "bc"
//var i = 0;
//anagram("a" + "b", "c")---> anagram("ab", "c")
//anagram("ab" + "c", [nothing here])
//base case hit, so uniqueOutput["abc"] = 1;
//var i = 1; --> this applies to the string "bc". the loop gets reset to i = 0 once you have a new string to worth with (like below, with "b")
//anagram("a" + "c", "b")
//anagram("ac", "b")
//anagram("ac" + "b", "" )
//base case hit, so uniqueOutput["acb"] = 1;
//STEP 3: increment up on the original string input ("abc") --> so now you are dealing with str[i] === b
//var i = 1;
//anagram("" + "b", "a" + "c")
//anagram("b", "ac") ---> now we need to loop through "ac"!
//anagram("b" + "a", "c")
//anagram("ba", "c")
//anagram("bac", "")---> base case hit, uniqueOutput["bac"] = 1;
//anagram("b", "ac")
//anagram("b" + "c", "a") ---> anagram("bc", "a")
//anagram("bca", "") ---> base case hit, uniqueOutput["bca"] = 1;
//STEP 4: increment up on the original string input ("abc") ---> str[i] === c
//var i = 2;
//anagram ("" + "c", "ab")---> anagram("c", "ab")
//now we need to loop through "ab!" c's index stays the same.
//anagram("c" + "a", "b") ---> anagram("ca", "b")
//anagram("cab", '')---> uniqueOuput["cab"] = 1;
//anagram("c" + "b", "a") ---> anagram("cb", "a")
//anagram("cba", "")----> uniqueOutput["cba"] = 1
From your comments above:
// first iteration: i = 0
// anagram('' + 'a' + 'bc' [from str.slice(0 +1)]) ---> resolves to "abc") --->
Actually on i = 0, the arguments passed to anagram are:
anagram('' + 'a', '' + 'bc');
which evaluates to:
anagram('a', 'bc');
Then within that call to anagram, we again loop over str, which is now just 'bc'. That will result in 2 more calls to anagram which will be
anagram('a' + 'b', '' + 'c'); // i = 0
anagram('a' + 'c', 'b' + ''); // i = 1
which evaluate to:
anagram('ab', 'c');
anagram('ac', 'b');
And the second one of those calls will result in another call to anagram with these arguments:
anagram('acb', '');
which gets added to uniqueOutput as str is now empty.
Only after all that has executed will the code return to the outermost call of anagram and i will increment as per your comment:
//second iteration: i = 1. we are still in the original call from line 37.
You are missing the second iteration.. this is the execution flow in comments:
// anagram('', 'abc') level 0
// condition false... level 0
// first iteration: i = 0 level 0
// anagram(a', 'bc') ( creating new execution context level 1 )
// condition false.. level 1
// iteration 1... level 1
// anagram('ab', 'c') ( creating new execution context level 2 )
// condition false.. level 2
// iteration 1... level 2
// anagram('abc', '') ( creating new execution context level 3 )
// condition true.. push "abc"
// end for of level 2 context execution
// iteration 2... level 1
// anagram('ac', 'b') ( creating new execution context level 2 )
// condition false.. level 2
// iteration 1... level 2
// anagram('acb', '') ( creating new execution context level 3 )
// condition true.. push "abc" level 3
// end for of level 2 execution
// end for of level 1
// second iteration of level 0....
// keep this pattern till end for of level 0..
// end anagram level 0
As you can see, each iteration of the level 0 is going to push 2 words to the object. If we follow your logic, each iteration is pushing just one, take into consideration that recursion is just like adding more code in that exact place, once the function call finishes the execution flow returns to the place where it was before the call of the function.