70. 爬楼梯

题目

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例1:

1
2
3
4
5
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例2:

1
2
3
4
5
6
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

提示:

1
1 <= n <= 45

解法:

解法一:计算Fibonacci数列项

爬一个台阶有一种方法,两个台阶有两种方法,那么三个台阶就有1(爬一个台阶) + 2(爬两个台阶)= 3种方法,依次类推,f(n) = f(n -1) + f(n - 2)。很明显,这是一个求fibonacci数列的问题。

Java

1
2
3
4
5
6
7
8
9
public int climbStairs(int n) {
if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
} else {
return climbStairs(n - 1) + climbStairs(n - 2);
}
}

提交之后,发现运行超时,那明显,就是计算量过大,于是,需要将中间计算的结果保存起来。

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public int climbStairs(int n) {
if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
}

int begin = 3;
int f1 = 1;
int f2 = 2;
int f3 = 0;
while (begin <= n) {
f3 = f1 + f2;
f1 = f2;
f2 = f3;
begin++;
}
return f3;
}

解法二:动态规划

从题目可知,走到第N级台阶有两种方法,从N-1级台阶过来,或者从N-2级台阶过来。那么走到dp[N]的总台阶数就是从dp[N-1]或者从dp[N-2]台阶过来的总数和。

状态转移方程就是

dp[1] = 1;

dp[2] = 2; // 从第一步,到第二步;直接到第二步

dp[N] = dp[N-1] + dp[n-2]

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public int climbStairs(int n) {
if (n == 1) {
return 1;
}

if (n == 2) {
return 2;
}
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3;i <= n;i++) {
dp[i] = dp[i - 1] + dp[i -2];
}
return dp[n];
}

解法三:使用fibonacci公式,求对应项

公式说明

Java

1
2
3
4
5
public int climbStairs(int n) {
double sqrt5=Math.sqrt(5);
double fibn=Math.pow((1+sqrt5)/2,n+1)-Math.pow((1-sqrt5)/2,n+1);
return (int)(fibn/sqrt5);
}
0%