70. 爬楼梯 |刷题打卡

93 阅读1分钟

掘金团队号上线,助你 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) = 1f(2) = 2f(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);
};

仅供学习参考

参考题目