The problem: find a number of possible ways from top left corner to bottom right corner in MxN grid while you can only move down or right.
Here are two algorithms I have written. Results look ok but I can't figure out time and space complexity, I have some guesses about what the complexities might be but I can't prove them in a "proper" way.
Naive algorithm:
function gridTravel(m, n) {
if(m<1 || n<1) return 0;
if (m === 1 || n === 1) return 1;
return gridTravel(m-1, n) + gridTravel(m, n-1);
};
console.log(gridTravel(10,10));
My guesses:
- Space complexity - O(n+m)? The longest possible call stack seems to scale "linearly" so assuming some approximation it would be O(n+m) but I can't really prove it or disprove it.
- Time complexity is exponential because each position can create 2 new positions - O(2^n) or O(2^n+m), not sure which is more fitting.
m:n
m-1:n m:n-1
m-2:n m-1:n-1 m-1:n-1 m:n-2
But again, I don't feel confident with this explanation because it isn't simmetrical tree it just looks like it at the beginning.
Naive algo + memoization:
seenGrids = {};
const gridTravel = (m, n) => {
if(m<1 || n<1) return 0;
if (m === 1 || n === 1) return 1;
if (`${m}:${n}` in seenGrids || `${n}:${m}` in seenGrids) {
return seenGrids[`${m}:${n}`] || seenGrids[`${n}:${m}`];
}
seenGrids[`${m}:${n}`] = gridTravel(m-1, n) + gridTravel(m, n-1);
return seenGrids[`${m}:${n}`];
};
My guesses:
- Space - O(n*m)? Call stack still seems to be linear but now we have this growing object
seenGridswhich based on my intuition should scale kind of in a quadratic way? I have no idea how to prove it or disprove it, when I ranconsole.log(Object.keys(seenGrids).length)for200x200grid I got19900which isn't eitherm*norm+nso is it linear or quadratic? - Time - O(n*m)? - this is the hardest for me to wrap my head around. It shouldn't be exponential anymore because a lot of subtrees are skipped thanks to saved answers but I have no idea how to derive time complexity in a "proper" way.