LeetCode刷题挑战-javascript:70.爬楼梯

132 阅读1分钟

background.webp

「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

题目

假设你正在爬楼梯。需要 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 阶

解题思路

方法一:暴力破解

递归注意点:

  1. 注意爆栈
  2. 存在重复的调用计算
// 全局变量,表示递归的深度
let depth = 0; 
function climbStairs(n) {
    // 防止爆栈
    ++depth;
    if (depth > 1000) {
        throw new Error('小心爆栈');
    }

    if (n < 1) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    if (n == 2) {
        return 2;
    }
    return climbStairs(n - 2) + climbStairs(n - 1);
};
  • 时间复杂度 O(2^n)
  • 空间复杂度 O(n)

方法二:备忘录递归

解法1的优化,备忘录递归,使用哈希表存储每次计算出来的结果,相当于备忘录,起到减枝的作用,去除重复调用(重叠子问题)的计算

function climbStairs(n) {
    let mapData = new Map();
    return myClimbStairs(n, mapData); 
}

function myClimbStairs(n, mapData) {
    if (n < 1) {
        return 0;
    }
    if (n === 1) {
        return 1;
    }
    if (n === 2) {
        return 2;
    }
    // 已经计算过直接返回
    if (mapData.get(n)) {
        return mapData.get(n);
    }

    let value = climbStairs(n - 1) + climbStairs(n - 2);
    mapData.set(n, value);
    return value;
}
  • 时间复杂度O(n)
  • 空间复杂度O(n)

方法三:动态规划(推荐)

思路

  1. 状态是dp[i],dp[i]为所求结果

  2. 选择是i,即走到第i级

  3. dp数组含义:dp[i]表示第i级台阶的走法,第i级台阶的走法是第i - 1级和第i - 2级的走法之和

  4. 状态转移方程

    • 当n = 1时,dp[1] = 1
    • 当n = 2时,dp[2] = 2
    • 当n >= 3时 dp[n] = dp[n-1] + dp[n-2]
  5. 基础情况为dp[1] = 1,dp[2] = 2

解法类似:斐波拉契数

/** 
 * 
 * @param {*} n 
 */
function climbStairs(n) {
    if (n < 1) {
        return 0;
    }
    // base case
    if (n === 1) {
        return 1;
    }
    if (n === 2) {
        return 2;
    }

    // 因为状态转移只和上一次迭代和上上次迭代的结果有关,所以只用两个变量存储,不需要用数组,减少了空间
    let pre = 1;
    let cur = 2;

    for (let i = 3; i <= n; i++) {
        let sum = pre + cur;
        pre = cur;
        cur = sum;
    }

    return cur;
}

优化版解法如下👇:

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;
};
  • 时间复杂度O(n)
  • 空间复杂度O(1)

结束语

这里是小葵🌻,只要把心朝着太阳的地方,就会有温暖~

让我们一起来攻克算法难关吧!!