# 剑指offer10 青蛙跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
# 解答
动态规划
/**
 * @param {number} n
 * @return {number}
 */
var numWays = function(n) {
  if(n<=1) return 1;
  let fibNMinus2 = 1;
  let fibNMinus1 = 1;
  let fib = n
  for(let i= 2;i<= n;i++) {
      fib = (fibNMinus1 + fibNMinus2) % (1e9+7) // 在循环里面计算才不会ac不通过,取模精确度准确
      fibNMinus2 = fibNMinus1
      fibNMinus1 = fib
  }
  return fib
};
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 类似题目
- 爬楼梯
 
TIP
本问题其实常规解法可以分成多个子问题,爬第n阶楼梯的方法数量,等于 2 部分之和
爬上 n-1 阶楼梯的方法数量。因为再爬1阶就能到第n阶
爬上 n-2 阶楼梯的方法数量,因为再爬2阶就能到第n阶
所以我们得到公式 dp[n] = dp[n-1] + dp[n-2]
同时需要初始化 dp[0]=1 和 dp[1]=1
时间复杂度:O(n)
/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
    const dp = [];
    dp[0] = 1;
    dp[1] = 1;
    for(let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
};
// 时间/空间复杂度均为: O(n)
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
优化复杂度:
dp[i]只与dp[i-1]和dp[i-2]有关,没有必要存储所有计算过的dp项。用两个临时变量去存这两个状态就好。
const climbStairs = (n) => {
  let prev = 1;
  let cur = 1;
  for (let i = 2; i < n + 1; i++) {
    const temp = cur;   // 暂存上一次的cur
    cur = prev + cur;   // 当前的cur = 上上次cur + 上一次cur
    prev = temp;        // prev 更新为 上一次的cur
  }
  return cur;
}
// 空间复杂度O(1)
 1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
面试题08.01 三步问题
TIP
三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。
/**
 * @param {number} n
 * @return {number}
 */
var waysToStep = function(n) {
  let dp = new Array(n)
  dp[0]=1
  dp[1]=2
  dp[2]=4
  if(n<=3) {
      return dp[n-1]
  } else {
      for(let i=4;i<=n;i++) {
          dp[i-1] = (dp[i-2]+dp[i-3]+dp[i-4]) % (Math.pow(10,9)+7) // 1e9+7
      }
      return dp[n-1]
  }
};
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18