# 爬楼梯

爬楼梯-简单

假设你正在爬楼梯。需要 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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 方法1: 动态规划

题解

复杂度分析:

  • 时间复杂度:循环执行 n 次,每次花费常数的时间代价,故渐进时间复杂度为 O(n)。
  • 空间复杂度:这里只用了常数个变量作为辅助空间,故渐进空间复杂度为 O(1)。
/**
  f(x)=f(x−1)+f(x−2)
  f(0) = 1
  f(1) = 1
  后续的都可以通过状态转移公式得出
  利用滚动数组,将空间复杂度优化为 O(1)
 */

function climbStairs(n: number): number {
  let p: number = 0, q: number = 0, r: number = 1;
  for (let i = 1; i <= n; ++i) {
    p = q;
    q = r;
    r = p + q;
  }
  return r;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. 递归

// 和斐波那契数列一样
function climbStairs(n){
  let arr = [0,1,2];
  for(let i = 3; i <= n; i++){
    arr[i] = arr[i - 1] + arr[i - 2];
  }
  return arr[n];
}
1
2
3
4
5
6
7
8

# 其他方法

数学相关的两种,暂时跳过

# 进阶

对原始题目增加限制条件

  1. 每次你可以爬 1 或 2 个台阶
  2. 不能连续跳两个台阶。(个人理解为这次跳了两个台阶,下次不能再跳两个台阶)

题解

/**
 不可以连续跳两个,则前两步不可以跳两个,则前两步跳 2 + 1,可以认为一次跳 3 步,注意这三步实际是 (1 + 2) 步
 f(x) = f(x-1) + f(x-3)
 f(0) = 1
 f(1) = 1
 f(2) = 2
 举例:
 已知条件
 f[1][1] = 1
 f[2][1] = 1 + 1
 f[2][2] = 2
 f[3][1] = 1 + 1 + 1
 f[3][2] = 2 + 1
 f[3][3] = 1 + 2

 f[4][1] = f[1][1] + 3(步) = 1 + (1 + 2)
 f[4][2] = f[3][1] + 1 = 1 + 1 + 1 + 1
 f[4][3] = f[3][2] + 1 = 2 + 1 + 1
 f[4][4] = f[3][3] + 1 = 1 + 2 + 1

 f[5][1] = f[2][1] + 3(步) = 1 + 1 + (1 + 2)
 f[5][2] = f[2][2] + 3(步) = 2 + (1 + 2)
 f[5][3] = f[4][1] + 1(步) = 1 + (1 + 2) + 1
 f[5][4] = f[4][2] + 1(步) = 1 + 1 + 1 + 1 + 1
 f[5][5] = f[4][3] + 1(步) = 2 + 1 + 1 + 1
 f[5][6] = f[4][4] + 1(步) = 1 + 2 + 1
 */

function climbStarts2(int n) {
  if(n === 1) return 1; // 防止数组溢出(f[2])
  int[] f = new Array(n + 1);
  f[0] = 1;
  f[1] = 1;
  f[2] = 2;
  for(int i = 3; i <= n; i++) {
    f[i] = f[i - 1] + f[i - 3];
  }
  return f[n];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39