携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
爬楼梯
假设你正在爬楼梯。需要
n
阶你才能到达楼顶。每次你可以爬1
或2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
来源:力扣(LeetCode) 70. 爬楼梯
分析
根据题目推演
- 当只有1阶的时候,有1种方法,当有2阶的时候,可以1+1,也可以2,有2种方法,当有3阶的时候,可以1+1+1,1+2或者2+1,有3种方法,当有4阶的时候,可以是在爬2阶方法的基础上再爬2层,也可以是在爬3阶方法的基础上再爬1层,所以爬4阶的方法就是2+3=5,以此类推
- f(1)=1,f(2)=2,f(3)=3,f(4)=5...
方法一:动态规划
- 递推公式:f(n) = f(n-1)+f(n-2)
- 因为只需要得到爬到N阶的方法数,不需要保存所有的数,只需要维护f(n-2)、f(n-1)和f(n)的值,把这三个值看成一个数组的窗口,随着遍历,窗口向后移动,空间复杂度可以做到O(1)
代码
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
if(n===0) return 0;
if(n===1) return 1;
if(n===2) return 2;
let arr = [1,2];
for(let i=2;i<n;i++){
arr[i] = arr[i-1]+ arr[i-2];
}
return arr[n-1];
};
方法二:数论-斐波那契数列
- 当遇到这种情况,如果有些数学敏感,通过补充一个f(0)=1,于是这个数列变成了1,1,2,3,5,8...
- 显然,这就是菲波那切数列,求第N个斐波那契数列的值
- 此时可以秀一下数学肌肉,熟背斐波那契数列的通项公式,时间复杂度可以做到O(1)
代码
/**
* @param {number} n
* @return {number}
*/
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);
};
总结
- 今天题目难度级别为简单,有多种方法,可以递归,可以得到递推公式后进行动态规划,也可以直接使用通项公式,当N很大的时候,递归会爆栈,通项公式容易出现算术的精度问题,动态规划可能是最安全。
- 所以,秀数学肌肉很炫酷,也应该重视内功心法
- 今天又是有收获的一天