掘金团队号上线,助你 Offer 临门! 点击 查看详情
一、题目描述:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
二、思路分析:
- 这个感觉有点像数学题,要找规律
f(1) = 1,
f(2) = 2,
f(3) = 3,
f(4) = 5,
f(5) = 8
...
有没有发现
f(3) = f(1) + f(2);
f(4) = f(2) + f(3);
三、AC 代码
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
let p = 0, q = 0, r = 1;
for (let i = 1; i <= n; ++i) {
p = q;
q = r;
r = p + q;
}
return r;
};
执行用时:92 ms
内存消耗:37.7 MB
四、总结
- 当然不止一种方法,官方把上面的方法叫做:动态规划(f(x)=f(x−1)+f(x−2));
还有一种矩阵快速幂,看着是线性代数里的东西,差不多忘了,比较复杂,就简单看看了
var climbStairs = function(n) {
const q = [[1, 1], [1, 0]];
const res = pow(q, n);
return res[0][0];
};
const pow = (a, n) => {
let ret = [[1, 0], [0, 1]];
while (n > 0) {
if ((n & 1) === 1) {
ret = multiply(ret, a);
}
n >>= 1;
a = multiply(a, a);
}
return ret;
}
const multiply = (a, b) => {
const c = new Array(2).fill(0).map(() => new Array(2).fill(0));
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 2; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
}
}
return c;
}
- 还有一个方法:通项公式, 就了解一下,没深入研究
var climbStairs = function(n) {
const sqrt5 = Math.sqrt(5);
const fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1);
return Math.round(fibn / sqrt5);
};
仅供学习参考