Skip to content

Instantly share code, notes, and snippets.

@RP-3
Created February 9, 2020 22:14
Show Gist options
  • Save RP-3/c1035671ce6a78936452fa659b716d63 to your computer and use it in GitHub Desktop.
Save RP-3/c1035671ce6a78936452fa659b716d63 to your computer and use it in GitHub Desktop.
// 'Pure' recursive
// Note that this is almost literally just writing out the question statement
var uniquePaths = function(m, n) {
// also note this is a pure function: No side effects. No enclosed local vars
// Using an inner function just to keep things tidy and not pass (m, n) everywhere
const traverse = (i, j) => { // i, j are position on board
if(i === m-1 && j === n-1) return 1; // Count the number of ways the robot gets here.
// I.e., every time the robot gets here, return 1.
if(i >= m) return 0; // we are too far right. This is not a valid solution. Return 0.
if(j >= n) return 0; // we are too far down. This is not a valid solution either. Return 0.
// The robot can only move down and right.
return memo = traverse(i+1, j) // So try moving right
+ traverse(i, j+1); // And try moving down
};
return traverse(0, 0); // The robot starts at 0, 0
};
// Memoized recursive
// Literally add two lines and edit the returns.
// 1. Init a memo table
// 2. Check the memo table
// 3. Memoize return statements
var uniquePaths = function(m, n) {
const memo = new Array(m).fill(0).map(() => new Array(n).fill(null)); // 1. init memo table
const traverse = (i, j) => {
if(i === m-1 && j === n-1) return 1;
if(i >= m) return 0;
if(j >= n) return 0;
if(memo[i][j] !== null) return memo[i][j]; // 2. Check memo table
return memo[i][j] = traverse(i+1, j) + traverse(i, j+1); // Memoize return statement
};
return traverse(0, 0);
};
/*
Now console.log the memo table by changing line 41 to:
const result = traverse(0, 0); // save the solution
console.log(memo); // <---- this is the only real change
return result;
Logs the following for m=3, n=2.
Should look suspiciously familiar!
[
[ 3, 1 ],
[ 2, 1 ],
[ 1, null ]
]
Note that memo[i][j] === memo[i-1][j] + memo[i][j-1].
Isn't that your DP relationship?
Look again at your recurrence relationship...
return memo[i][j] = traverse(i+1, j) + traverse(i, j+1);
That's exactly what your 'DP' solution does.
So the advantages of getting a 'pure' recursive solution are that:
1. Sometimes it's easier
2. Your optimized 'DP' solution literally falls out at your feet
3. Your recursive solution won't *necessarily* explore the entire memo table.
The disadvantages of going recursive are:
1. Call stacks are lame
2. Sometimes it's harder
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment