一起刷LeetCode——爬楼梯(数组+数学)

83 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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很大的时候,递归会爆栈,通项公式容易出现算术的精度问题,动态规划可能是最安全。
  • 所以,秀数学肌肉很炫酷,也应该重视内功心法
  • 今天又是有收获的一天