Leetcode 104 Maximum Depth of Binary Tree - javascript

I am reviewing the solution to this leetcode problem. The solution is the following:
var maxDepth = function(root) {
let maxNode = (node, sum) => {
if (node === null) {
return sum;
}
return Math.max(maxNode(node.left, sum + 1), maxNode(node.right, sum + 1));
}
return maxNode(root, 0);
};
I was wondering why return maxNode(root, 0); must include a return. Is it required to 'activate' the inner function? If so, why doesn't just maxNode(root, 0) just 'activate' it?

The solution includes "recursion", which means the maxNode function is called multiple times from within itself. This requires the maxNode function to return a value to it's calling "instance".
The maxDepth function has a return statement to return the calculated maxNode value.

This function maxDepth will determine the maximum depth of a binary tree.
You would use it like this:
let depth = maxDepth(treeRoot);
Without the return, the function will determine the depth but you will not get the result when you call the function.

It is a another construction of a recursive function by taking a sum as parameter for a recursion.
It could be easily rewritten to the below function where the adding of one is outside of the function call.
var maxDepth = function(node) {
if (!node) return 0;
return 1 + Math.max(maxNode(node.left), maxNode(node.right));
};

Related

Converting JavaScript function to C++

I was working on a Dynamic Programming Problem and was able to code up a Javascript solution:
function howSum(targetSum,numbers,memo = {}){
//if the targetSum key already in hashmap,return its value
if(targetSum in memo) return memo[targetSum];
if(targetSum == 0) return [];
if(targetSum < 0) return null;
for(let num of numbers){
let aWay = howSum(targetSum-num,numbers,memo);
if(aWay !== null){
memo[targetSum] = [...aWay,num];
return memo[targetSum];
}
}
//no way to generate the targetSum using any elements of input array
memo[targetSum] = null;
return null;
}
Now I was thinking over how I could translate this into a CPP code.
I would have to use a reference to an unordered map for the memo object.
But how should I go about returning the empty array and null values as in the base condition?Should I return an array pointer and realloc it when inserting an element?Wouldnt that be a C way of programming it?
Also how should I go about passing the default parameter to the memo unordered map in C++?Currently I have overloaded the function which creates the memo unorderd map and passes its reference.
Any guidance will be appreciated as I can solve future questions.
I was stuck in this problem too. This is how I made it work.
// howSum function
vector<int> howSum(int target, vector<int> numbers, unordered_map<int, vector<int>> &dp ){
// base case 1 - for dp
if(dp.find(target)!=dp.end()) return dp[target];
// making a vector to return in the following base cases
vector<int> res;
// base case 2
if(target == 0) {
return res;
}
// base case 3
if(target<0) {
res.push_back(-1); // using -1 instead of NULL
return res;
}
// the actual logic for the question
for(int i=0;i<numbers.size();i++){
int remainder = target - numbers[i];
vector<int> result = howSum(remainder,numbers,dp); // recursion
// if result vector doesn't contain -1, push target to result vector
if(find(result.begin(),result.end(),-1)==result.end()){
result.push_back(numbers[i]);
dp.emplace(target,result);
return result;
}
}
res.push_back(-1);
dp.emplace(target,res);
return res;
}
// main function
int main(){
vector<int>numbers = {20,50};
unordered_map<int, vector<int>> dp;
vector<int> res = howSum(300,numbers,dp);
for(int i=0;i<res.size();i++){
cout<<res[i]<<" ";
}
cout<<endl;
}
Here is my take at it:
#include <optional>
#include <vector>
#include <unordered_map>
using Nums = std::vector<int>;
using OptNums = std::optional<Nums>;
namespace detail {
using Memo = std::unordered_map<int, OptNum>>;
OptNums const & howSum(int targetSum, Nums const & numbers, Memo & memo) {
if (auto iter = memo.find(targetSum); iter != memo.end()) {
return iter->second; // elements are std::pair<int, OptNums>
}
auto & cached = memo[targetSum]; // create an empty optional in the map
if (targetSum == 0) {
cached.emplace(); // create an empty Nums in the optional
}
else if (targetSum > 0) {
for (int num : numbers) {
if (auto const & aWay = howSum(targetSum-num, numbers, memo)) {
cached = aWay; // copy vector into optional
cached->push_back(num);
}
}
}
return cached;
}
} // detail
std::optional<Nums> howSum(int targetSum, Nums const & numbers) {
detail::Memo memo;
return detail::howSum(targetSum, numbers, memo);
}
Some comments:
using two functions, one that creates the memo and passes it into the real implementation function is a good pattern. It makes the user-facing interface clean.
the "detail" namespace is just a name, no magic meaning, but is often used to indicate implementation detail.
In the implementation, I return references to an optional. This is an optimization to avoid copying the return vectors in every call where the algorithm unwinds from the recursion. This does require some care, however, because you must be careful to return references to objects that will outlive the local scope (so no returning std::nullopt, or the reference binds to a temporary optional, for example.) That is also why I always create the element in the memo object--even in the negative case--so I can return a reference to it safely. Note, operator[] applied to an unordered_map will create the element if it does not exist, while find will not.
Since the reference returned by the detail function has a lifetime only as long as the memo declared in the caller, the caller itself must return a copy of the optional it gets back, to ensure that the data is not destroyed during the cleanup of the function call. Note, it does not return a reference.
Also, the "if" inside the for loop has a little bit going on. It declares a local reference, initializes it to the result of the recursive call. That whole expression is a reference to optional, which has an implicit conversion to bool that is true if the optional holds a value. This is a useful idiom worth pointing out, though to be more explicit this is equivalent:
if (auto const & aWay = howSum(targetSum-num, numbers, memo); aWay.has_value())
Here's a fleshed out example, with a few test cases to show it work.
https://godbolt.org/z/cWrdhvM1n

Currying function with unknown arguments in JavaScript

In a recent interview, I was asked to write a function that adds numbers and accepts parameters like this:
add(1)(2)(3) // result is 6
add(1,2)(3,4)(5) // result is 15
The number of parameters is not fixed, and the arguments can be either passed in sets or individually.
How can I implement this add function?
Given your examples, the number of parameters is fixed in some ways.
As #ASDFGerte pointed out, your examples seem to return the result after three invocations. In this case a simple implementation without introducing terms like variadic and currying could be
function add(...args1){
return function(...args2){
return function(...args3){
return args1.concat(args2).concat(args3).reduce((a,b)=>a+b)}}}
console.log(add(1)(2)(3))
console.log(add(1,2)(3,4)(5))
Every invocation accepts a variable number of parameters.
However it would be nice to generalize the construction of this nested functions structure and you can accomplish that with currying.
But if you want to allow an arbitrary number of invocations, when you should stop returning a new function and return the result? There is no way to know, and this is a simple, unaccurate and partial explanation to give you the idea of why they said you cannot accomplish what they asked you.
So the ultimate question is: is it possible that you misunderstood the question? Or maybe it was just a trick to test you
Edit
Another option would be to actually invoke the function when no arguments are passed in, change the call to add(1)(2)(3)()
Here an example recursive implementation
function sum (...args) {
let s = args.reduce((a,b)=>a+b)
return function (...x) {
return x.length == 0 ? s : sum(s, ...x)
};
}
console.log(sum(1,2)(2,3,4)(2)())
At every invocation computes the sum of current parameters and then return a new function that:
if is invoked without parameters just return the current sum
if other numbers are passed in, invokes recursively sum passing the actual sum and the new numbers
I'm a bit late to the party, but something like this would work (a bit hacky though in my opinion):
const add = (a, ...restA) => {
const fn = (b, ...restB) => {
return add([a, ...restA].reduce((x, y) => x + y) + [b, ...restB].reduce((x, y) => x + y))
};
fn.valueOf = () => {
return [a, ...restA].reduce((x, y) => x + y)
};
return fn;
}
This function returns a function with a value of the sum. The tests below are outputing the coerced values instead of the actual functions.
console.log(+add(1,2)(3,4)(5)); // 15
console.log(+add(1)) // 1
console.log(+add(1)(2)) // 3
console.log(+add(1)(2)(3)) // 6
console.log(+add(1)(2)(3)(4)) // 10
Since it's a currying function, it will always return another function so you can do something like this:
const addTwo = add(2);
console.log(+addTwo(5)); // 7
using reduce and spread it can be done as below
function calc(...args1){
return function (...args2){
return function (...args3){
let merge = [...args1, ...args2, ...args3]
return merge.reduce((x ,y)=> x + y) ;
}
}
}
let sum = calc(10)(1)(4);
console.log("sum",sum);
They probably wanted to know how comfortable you were with "javascript internals", such as how and when methods like Function#toString and Function#valueOf, Function#[Symbol.toPrimitive] are called under the hood.
const add = (...numbers) => {
const cadd = (...args) => add(...args, ...numbers);
cadd[Symbol.toPrimitive] = () => numbers.reduce((a, b) => a + b);
return cadd;
}
console.log(
`add(1,2)(3,4)(5) =>`, add(1,2)(3,4)(5),
); // result is 15
console.log(
`add(1,2) =>`, add(1,2),
); // result is 3
console.log(
`add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5) =>`, add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5),
); // result is 32

What's wrong with my implementation of the memoize function? [duplicate]

I'm trying to use memoization to optimize an explicitly self recursive implementation of the Fibonacci function. The implementation which is fairly standard (a simple and rather naïve implementation though to focus on the actual problem) follows.
Function.prototype.memoize = function () {
var originalFunction = this,
slice = Array.prototype.slice;
cache = {};
return function () {
var key = slice.call(arguments);
if (key in cache) {
return cache[key];
} else {
return cache[key] = originalFunction.apply(this, key);
}
};
};
Now, when creating and memoizing a function as follows, this works1. (Scenario 1)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}.memoize();
console.log(fibonacci(100));
However, the following does not.2 (Scenario 2)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};
console.log(fibonacci.memoize()(100));
And neither does this.2 (Scenario 3)
function fibonacci(n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci.memoize()(100));
My assumption is that because of the different ways of calling memoize() on the functions, something is changing. Note that the functions are otherwise identical. I suppose that this could be due to the fact that other than in the first instance, only the first call is memoized, not the recursive calls.
Question
If my supposition above is indeed correct, then why is this happening? Can someone explain in detail how the latter two scenarios differ from the first?
1To work in this instance means to return the 100th Fibonacci number since it is only possible to compute it recursively if memoization is used.
2To not work is to crash the browser.
Yes, it's right that only the first call is memoized in the second and third scenarios.
In the first scenario the reference to the original function only exists as a value, then memoize is applied to that and the fibonacci variable contains the reference to the memoized function.
In the second and third scenario fibonacci is a reference to the original function. The value of the expression fibonaci.memoize() that contains the reference to the memoized function only exist as a value before it is called once.
The memoize method doesn't change the original function, instead it returns a new function that wraps the original function. The original function is unchanged, and to use the memoization you have to call the function returned by the memoize method.
In the first scenario when the function makes a recursive call to fibonacci, it's the memoized function that is used. In the second and third scenarios when the recursive call is made, fibonacci is the original function instead.

The error of my Javascript function which supposed to return the length of an array if an array is given and return zero otherwise

I don't know much programming and I'm learning Javascript for a couple of days now so my question might be very easy, apologize in advance:
The question is:
Create a function named 'arrayCounter' that takes in a parameter which is an array. The function must return the length of an array passed in or 0 if a 'string', 'number' or 'undefined' value is passed in.
And I've done this:
function arrayCounter(i) {
var no = ['string', 'undefined', 'number'];
for (j = 0; j < no.length; j += 1) {
if(typeof(i) === no[j]) {return 0}
}
return i.length
Why my code is wrong?
You should make use of JavaScript's Array.isArray(arg) function, which tells if you some provided argument arg is an array. Using this function, we will check to see if the argument i passed to your function arrayCounter is an array. If it is, we return its length. Otherwise, we return 0, like such:
function arrayCounter(i) {
// if the argument is an array, return its length
if (Array.isArray(i)) {
return i.length;
}
// otherwise, return zero
else {
return 0;
}
};
If you want your code to be slightly less readable but a bit more concise, you can use JavaScript's conditional ternary operator, like such (as alluded to by #adeneo above):
function arrayCounter(i) {
return (Array.isArray(i) ? i.length : 0);
};

Emulate/use Continuations in JavaScript?

I have a function that computes product of numbers in an array. The function should work like this
function prod (array){
//compute and return product
}
var arr = [1,2,3,0,4,5,0,6,7,8,0,9];
the function call:
prod(arr); //should return 6
prod(arr); //should return 20
prod(arr); //should return 336 (6*7*8)
prod(arr); //should return 9
prod(arr); //should return 0
prod(arr); //should return 0
prod(arr); //should return 0
In scheme, this is done with continuations, by storing previous state of the function (state of the function is captured just before its exit point) see this
So, in short, I want the javascript function return different values at different times with same parameter passed everytime.
JavaScript is a well designed language, so I hope there must be something which can emulate this. If there happens to be nothing in JS to do it, I do not mind to conclude with failure and move on. So, feel free to say its impossible.
Thanks.
JavaScript is not capable of supporting continuations: it lacks tail-calls.
Generally I would write this to use a "queue" of sorts, although CPS is also do-able (just have a finite stack :-) Note that other state can also be captured in the closure, making it an "explicit continuation" of sorts ... in a very gross sense.
Example using a closure and a queue:
function prodFactory (array){
// dupe array first if needed, is mutated below.
// function parameters are always locally scoped.
array.unshift(undefined) // so array.shift can be at start
// also, perhaps more closured state
var otherState
// just return the real function, yippee!
return function prod () {
array.shift()
// do stuff ... e.g. loop array.shift() and multiply
// set otherState ... eat an apple or a cookie
return stuff
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
// array at "do stuff", at least until "do stuff" does more stuff
prod() // [1,2,3,0,4,5,0,6,7,8,0,9]
prod() // [2,3,0,4,5,0,6,7,8,0,9]
prod() // [3,0,4,5,0,6,7,8,0,9]
Happy coding.
"Finished implementation". Although this particular problem can avoid array mutation and just use an index: the same concepts apply. (Well, slightly different. With just an index the closed over variable would be altered, whereas with this approach an object is mutated.)
function prodFactory (array) {
array = array.slice(0)
return function prod () {
var p = 1
for (var n = array.shift(); n; n = array.shift()) {
p *= n
}
return p
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
prod() // 6
prod() // 20
prod() // 336
You can give the function a property that will be remembered between calls:
function prod (array){
if (typeof prod.index === "undefined" || prod.currentArray != array) {
prod.currentArray = array;
prod.index = 0;
}
if (prod.index >= array.length)
return 0;
//compute and return product
var p = 1,
c;
while (prod.index < array.length) {
c = array[prod.index++];
if (c === 0)
return p;
p *= c;
}
return p;
}
I'm just guessing from your description of what should be returned that on an individual call to the function it should take the product of all of the numbers up to but not including the next zero or the end of the array. Calls after the end of the array should return 0? I may have the algorithm wrong for that, but you get the idea for what I'm suggesting to remember the function state between calls.
I've added a property to remember the current array being processed. As long as you keep passing the same array in to the function it will continue with the next elements, but if you pass a different array it will reset...
you can try something like
var index = 0;
function prod (array){
if(index < array.length){
var prod=1;
for(int i=index;i<array.length;i++){
if(array[i] != 0){
prod = prod * array[i];
}
else{
index = i+1;
return prod;
}
}
}
return 0;
}
this will update the global variable index everytime the function is called.
What you're looking for here are generators. As of 1.7, JavaScript supports them.

Categories

Resources