【摸摸鱼】算法 —— 爬楼梯

199 阅读1分钟

描述:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例一:
输入:n = 2,输出:2;
解释:有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

示例二:
输入:n = 3,输出:3
解释:有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

看完题目及示例,在这里想到了中学数学\color{#FF0000}{数学}计算题,翻一翻落灰的数学课本,数列——斐波那契数列\color{#FF0000}{斐波那契数列}
回忆:斐波那契数列指的是每一项都等于前两项之和的数列,定义为F[1]=1,F[2]=1, F[n]=F[n-1]+F[n-2](n>=3)。 由此想到了
方案一:递归

// 这里需要单独考了前2级台阶
// n=1时 f(1) = 1
// n=2时 f(2) = 2
const step = (n) => {
    if (n < 3) {
        return n;
    }
    return step(n-1) + step(n-2);
};

很明显,递归相当于遍历了许多重复的节点,时间复杂度较高O(n^2); 根据递归及上面步骤分析,每一次计算结果都依赖上一次的计算结果, 由此有方案二、方案三:
方案二:(用数组存储计算结果) —— 动态规划

const step = (n) => {
    if (n < 1) return;
    let dp = [1, 1];
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i-1] + dp[i-2];
    };
    return dp[n];
}

方案三:(滚动数组)

const step = (n) => {
    if (n < 3) {
        return n;
    }
    let first = 1;
    let second = 2
    for (let i = 3; i <= n; i++) {
        second = first + second;
        first = second - first;
    }
    return second;
}