【发布时间】:2021-11-11 19:22:37
【问题描述】:
问题:在 MxN 网格中从左上角到右下角找到多种可能的方式,而你只能向下或向右移动。
这是我编写的两种算法。结果看起来不错,但我无法计算出时间和空间的复杂性,我对可能的复杂性有一些猜测,但我无法以“正确”的方式证明它们。
朴素算法:
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));
我的猜测:
- 空间复杂度 - O(n+m)?可能的最长调用堆栈似乎是“线性”扩展的,因此假设一些近似值将是 O(n+m),但我无法真正证明或反驳它。
- 时间复杂度是指数级的,因为每个位置可以创建 2 个新位置 - O(2^n) 或 O(2^n+m),不确定哪个更合适。
m:n
m-1:n m:n-1
m-2:n m-1:n-1 m-1:n-1 m:n-2
但同样,我对这个解释没有信心,因为它不是对称树,它只是一开始的样子。
朴素算法 + 记忆:
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}`];
};
我的猜测:
- 空间 - O(n*m)?调用堆栈似乎仍然是线性的,但现在我们有了这个不断增长的对象
seenGrids,根据我的直觉,它应该以二次方式缩放吗?我不知道如何证明或反驳它,当我为200x200网格运行console.log(Object.keys(seenGrids).length)时,我得到19900,它既不是m*n也不是m+n,所以它是线性的还是二次的? - 时间 - O(n*m)? - 这对我来说是最难缠的。它不再是指数级的,因为由于保存了答案,很多子树都被跳过了,但我不知道如何以“正确”的方式推导时间复杂度。
【问题讨论】:
标签: javascript algorithm time-complexity big-o space-complexity