Incrementing variable passed into my javascript recursive calls refusing to update - javascript

I'm trying to solve leetcode 112.Path Sum. I pass in currSum as 0 initially and want to increment currSum value by adding previous currSum value to current root.val - but currSum is not increasing, see code below:
var hasPathSum = function(root, targetSum) {
var result = helper(root, targetSum, 0);
return result;
};
function helper(root, targetSum, currSum){
if(root === null) return false;
currSum = currSum + root.val;
console.log(currSum);
if(root.left === null && root.right === null && currSum === targetSum){
return true;
}
return hasPathSum(root.left, targetSum, currSum) || hasPathSum(root.right, targetSum, currSum);
}
can someone please point me to what i am doing wrongly. Thanks in advance.
See link to the problem statement here https://leetcode.com/problems/path-sum/
What i expect currSum to be is:
5
9
20
27
22
...
but what i get is:
5
4
11
7
2
8
13
4
1
Observe that it is just printing back the current root.val at each recursive call.

Whenever you call this function
var hasPathSum = function(root, targetSum) {
var result = helper(root, targetSum, 0);
It will call helper with last parameter as zero and it only accepts two parameters - root and targetSum
Therefore when you call at the end of function
hasPathSum(root.left, targetSum, currSum)
The currSum is not used in any way, it is just lost
I have not checked the logic itself, but to keep the currSum value you need to use it in this way:
return helper(root.left, targetSum, currSum) || helper(root.right, targetSum, currSum);

Related

On the Leetcode Palindrome problem (number 234), why is my JavaScript solution not passing all the test cases?

I'm working on the palindrome question, and failing the [1,2] test case. Below is my code:
var isPalindrome = function(head) {
var listLength = head.length ? head.length : 0;
if (listLength === 0 || listLength === 1) return true;
var curNode = head[0];
var tailNode = head[listLength - 1];
if (listLength === 2) {
// if (curNode === tailNode) return true;
// return false;
return curNode === tailNode;
}
if (curNode !== tailNode) return false;
head.shift();
head.pop();
return (isPalindrome(head));
};
When I run the test case in vscode on my device, I get false for [1,2] (which is the expected result) but the uploaded version on leetcode is failing that test and returning true instead. I have no clue why. My solution is by no means the best solution but I tried a handful of tests on my local and it seemed to get the job done. Any advice on how to fix this, or insight as to why I'm failing the test case on leetcode?
Initially I thought it was the way I structured my conditional when listLength is 2, but I changed that to something I'm sure would work and it didn't change the outcome.
edit: link to leetcode question https://leetcode.com/problems/palindrome-linked-list/
As #JoshuaWood pointed out, I was operating under the assumption that my list had array properties native to JavaScript arrays, but this is an incorrect way of viewing the problem. I had to quite literally handle the list with the pointer and data they provided me. (see definition below)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* #param {ListNode} head
* #return {boolean}
*/
Once I realized I wouldn't be able to use any array properties, and just use the properties given to me in the definition above, I was able to reformat my solution and come up with this:
var isPalindrome = function(head) {
let curr = head;
var len = 0;
let last = null;
let secondToLast = null;
if (curr.val !== null) len = 1;
if (curr && curr.next === null) return true;
while (curr.next !== null) {
len++;
secondToLast = curr;
curr = curr.next;
}
last = curr;
if (len === 2) {
if (head.val === last.val) return true;
return false;
}
if (head.val === last.val) {
secondToLast.next = null;
last.val = null;
last = null;
return isPalindrome(head.next);
} else {
return false;
}
}
Basically I can navigate to the end of the list, store what's at the end, compare it to the beginning, and pop off those values if they are equal. If they're not equal, then the list is not a Palindrome. If they are, then I iterate to the next entry in the list and pop off the end. This continues until you either reach a list with only 1 or 2 left, does the final comparison if there are two, or simply returns true if there's only one node left since that node will be equal to itself.
Hope this helps! Once I realized that of course they wouldn't have array properties, it all made a lot more sense.

Getting False on a recursive function with if conditions trying to solve the "Palindrome" Challenge

So I was doing this popular challenge "palindrome" and I was copying this solution from the "Frontend Masters" Javascript Series and I'm getting a different output. I want to know if there is something that changes or am I missing something. This is my first question on StackOverflow because this is just MindF***k.
What is going on?
'use strict'
function isPalindrome(str) {
if (str.length <= 1) return true;
var first = str[0];
var last = str[str.length - 1];
if (first === last) {
console.log(str.substring(1, str.length - 1))
isPalindrome(str.substring(1, str.length - 1));
}
return false;
}
console.log(isPalindrome("abcdcba")) // Return false on my machine
I try this on the RunJS app as well as the VScode terminal and also I run Node on the file.
KEEP RETURNING FALSE !!
The function will return true if and only if the length of the input is <= 1:
if (str.length <= 1) return true;
Which it isn't:
isPalindrome("abcdcba")
The only other return statement in the function is:
return false;
It looks like you meant to return the recursive result:
return isPalindrome(str.substring(1, str.length - 1));
Otherwise the function never does anything with the result from calling itself recursively, and just defaults to returning false on the last line.
I fixed your code...
'use strict'
function isPalindrome(str) {
if (str.length <= 1) return true;
var first = str[0];
var last = str[str.length - 1];
if (first === last) {
console.log(str.substring(1, str.length - 1))
return isPalindrome(str.substring(1, str.length - 1));
}else return false;
}
console.log(isPalindrome("abcdcba")) //
I see recursive functions having two different parts:
Going forward when the function starts calling itself and stacking function calls.
in a reverse way going backward when all the stack functions start returning values. In your example this phase is kickoff just after if (str.length <= 1) return true or if first !== last.
I think you you did it totally right going forward, but there was a minor details in the come back. You need to remember that ones you have your solution you need to return values through all the calls back to the initial one.
A recursive function is kind of split in two:
function recursive{
//forward processing
..
resultValue = recursive()
..
// backward processing if needed
return kindOfResultValue //resultValue or a transformation if needed
}
Note: Remember to check all conditional branches of your recursive function to return always a value after calling itself

Final Value of a Variable in a JavaScript Recursive Function call

function even(num) {//console.log(num) => shows 1 & then 0 before terminating.
if (num === 0) {
return true;
} else {
return !even(num - 1);
}
}
console.log(even(1));
//Why Chrome Console shows num = 1 when .log is being executed.
The Else part of the recursive function even would run till num becomes 0 this is quite clear but the chrome developer console shows num = 1 print when console.log is logging
Is the final value going to be 0 or 1?
Screenshot after the calls are completed:
The function you provided will recursively call itself until num is 0, and then the results will bubble back up.
So:
even( 1 ) is called - current function: even( 1 )
even( 0 ) is called by even( 1 ) - current function: even( 0 )
even( 0 ) returns true back to even( 1 ) - current function: even( 1 )
even( 1 ) returns !true: false - current function: main, but even( 1 ) was the last function called.
At the end, the last version of even() the code was running in was even( 1 ). The debugger will show num = 1 because that was the last value num had before returning.
To see this in action:
function even(num) {
console.log( "num is: " + num + " before function" );
if (num === 0) {
return true;
} else {
var returnValue = !even(num - 1);
console.log( "num is: " + num + " after recursion" );
return returnValue;
}
}
console.log(even(5));
The response will be false for odd numbers, and true for even. That looks pretty exactly what you need. But this looks overcomplex, why don't do just
function even(num) {
return n % 2 == 0;
}
Yes chrome showing right when we use that kind of data structure like recursion then here what happen all call going to stack and all operation happening according to stack push and pop operation. So
when you pass 1 to function then basically what is happening the value of num is -
1 -> 0 in stack but when your condition is true now stack is releasing so it will back on original state and the last value is 1 so that why you are getting 1.

checking values before submitting form

Before I submit a form I want to check the values in the input.
Here I'm checking if a value is NOt equal to .5 or 1. or not a empty string.
form.onsubmit = function(e) {
var ftimes = document.getElementsByClassName("add_timebox");
var fflag = 0;
for(i=0;i< ftimes.length;i++) {
var value1 = ftimes[i].value;
console.log(value1);
if ( value1 !==.5 ||value1 !== 1 || (!IsStringEmpty(value1)) ){
fflag = 1;
console.log('inside');
}
}
if(fflag==1) {
alert('enter again' );
return false;
}
I have made many changes to the IF statement to try to get it correct.
But it is still going in the loop even when I know if shouldn't.
For example when i submit the form and i have one input value equal .22
then it should only give me 1 'inside' but in keeps repeating:
inside
.22
(empty string)
inside
....
You do not show how you are implementing your IsStringEmpty method, but if you are using something like this, then any number is also a non-empty string, so your if statement will always run.
function IsStringEmpty(str) {
return (!str || 0 === str.length);
}
So you need to change your ORs with ANDs, or it will never check the number conditions.
You can check if the value is not an empty string and is different from 0.5 and 1. Then your condition should be like this.
if (!IsStringEmpty(value1) && value1 !== 0.5 && value1 !== 1)
But, you are getting the value from a form, so it will be a string. Therefore, you are comparing strings and you need this.
if (!IsStringEmpty(value1) && value1 !== ".5" && value1 !== "1")
Although you will probably want to compare floats, in which case you need this.
if (!IsStringEmpty(value1) && parseFloat(value1) !== .5 && parseFloat(value1) !== 1))
So basically, when you enter 1, .5 or and empty string in all of the form fields, you skip the inside block. But if you have any other value in any of the fields, then the flag will be set to 1. If that is not what you meant, please update your question to be more specific.
Please check Plunker here.
Hope this helps.
you have to add a break; statment in your if condition once the if condition is satisfied.
if ( value1 !==.5 ||value1 !== 1 || (!IsStringEmpty(value1)) ){
fflag = 1;
console.log('inside');
break;
}

Trouble pushing to an array in JS

Below is just a section of my code but I know it's problematic because I can't get it to return any value except 'undefined'. I have been over this for hours and cannot figure it out.
I want to be able to input a number and have its factors pushed to an array. I have tested it by alerting the first item in the array and I get nothing. I'm sure this is a pretty easy but I just can't figure it out. Here is the code:
var numberInQuestion = prompt("Of what number are you wanting to find the largest prime factor?");
//determine factors and push to array for later use
var factorsArray = [];
function factors(numberInQuestion){
for(var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0){
return factorsArray.push[i];
} else {
continue;
}
}
};
factors(numberInQuestion);
alert(factorsArray[0]);
Thanks for any help!
you can only return one value
you must use (), not [] for calling push
factorsArray should be local to factors (put the definition inside the function)
the else { continue; } is useless
Here is the fully corrected code:
var numberInQuestion = prompt("Of what number are you wanting to find the factors of?");
//determine factors
function factors(numberInQuestion){
var factorsArray = []; // make it local
for (var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0){
factorsArray.push(i); // use (), and don't return here
} // no need for else { continue; } because it's a loop anyway
}
return factorsArray; // return at the end
};
var result = factors(numberInQuestion); // assign the result to a variable
alert(result);
Here's a JSFiddle.
You have an error in your pushing syntax. Correct syntax for pushing is -
factorsArray.push(i);
Also returning immediately from the function after finding the first divisor will not give you the full list. You probably want to return after you've found out all the divisors.
Taking all of the above into consideration, you should rewrite your function as follow -
function factors(numberInQuestion){
for(var i = 2; i < numberInQuestion - 1; i++){
if(numberInQuestion % i === 0) {
factorsArray.push(i);
}
}
}
and you will be OK.
You've coded this so that when you find the first factor your function returns immediately. Just get rid of the return keyword in that statement. (What "return" means in JavaScript and other similar languages is to immediately exit the function and resume from where the function was called.)
Oh, also, you call functions (like .push()) with parentheses, not square brackets.
The function should not return when pushing to the array. Return the array after executing the loop. The else clause is also unnecessary.
var numberInQuestion = prompt("Of what number are you wanting to find the largest prime factor?");
function factors(numberInQuestion){
var factorsArray = [];
for(var i = 2; i < numberInQuestion-1; i++){
if(numberInQuestion % i === 0 && isPrime(i)){
factorsArray.push(i);
}
}
return factorsArray;
};
var factors = factors(numberInQuestion);
alert(factors[factors.length-1]);
//From: http://stackoverflow.com/questions/11966520/how-to-find-prime-numbers
function isPrime (n)
{
if (n < 2) return false;
var q = Math.sqrt (n);
for (var i = 2; i <= q; i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
Given the purpose of the example two items must be considered
The code does not determine if the number is actually prime. The code will return the smallest factor possible since the loop starts at two and increments, then returns the first element in the array. The largest factor would actually be the last element in the array. I have corrected the example to find the greatest prime factor. You can test it via this fiddle: http://jsfiddle.net/whKGB/1/

Categories

Resources