问题描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
问题分析
这其实是一道很简单的动态规划问题,解决方法的步骤还是一样的,确定边界和状态转移方程,然而起初笔者怎么也想不出这个转态转移方程怎么得出,每次比前一次多一个阶梯,但可能爬楼梯方法多出了很多,貌似没那么容易得到转态转移方程,于是就把n从1-5的结果全部试了出来,发现有点像斐波那契数列,即res[n] = res[n-1] + res[n-2],顺手试试就通过了,虽然结果过通过了,但有点费解,为什么爬楼梯的结果和斐波那契数列一样呢?
笔者先是计算出了了n阶楼梯的表达式:
1.n为偶数时res[n] =
c
o
m
b
n
t
n
s
(
n
,
0
)
combntns(n,0)
combntns(n,0)+
c
o
m
b
n
t
n
s
(
n
−
1
,
1
)
combntns(n-1,1)
combntns(n−1,1)+
c
o
m
b
n
t
n
s
(
n
−
2
,
2
)
combntns(n-2,2)
combntns(n−2,2)+…+
c
o
m
b
n
t
n
s
(
n
−
n
/
2
,
n
/
2
)
combntns(n-n/2,n/2)
combntns(n−n/2,n/2)
2. n为奇数时res[n] =
c
o
m
b
n
t
n
s
(
n
,
0
)
combntns(n,0)
combntns(n,0)+
c
o
m
b
n
t
n
s
(
n
−
1
,
1
)
combntns(n-1,1)
combntns(n−1,1)+
c
o
m
b
n
t
n
s
(
n
−
2
,
2
)
combntns(n-2,2)
combntns(n−2,2)+…+
c
o
m
b
n
t
n
s
(
n
−
(
n
−
1
)
/
2
,
(
n
−
1
)
/
2
)
combntns(n-(n-1)/2,(n-1)/2)
combntns(n−(n−1)/2,(n−1)/2)
然后试图计算出res[n] = res[n-1] + res[n-2];结果失败,可能笔者数学不怎么好T T,反正就是计算失败。
通过这位大神(我与大神居然拥有相同的思想经历)的讲解爬楼梯与斐波那契数列.恍然大悟。
首先考虑第一步的走法:第一步可以走1级台阶,也可以走2级台阶。那么,设res(n)表示走n级台阶的走法数量,如果第一步走1级台阶,剩下的台阶数为n-1,也就是说这种情况下的走法是相当于rres(n-1);同理,如果第一步走2级台阶,剩下的台阶数为n-2,这样的走法相当于res(n-2);于是,得出递推公式:res[n] = res[n-1] + res[n-2]
按每次加一个楼梯,从后往前难以得出结果,而把加的楼梯放前面,结果一目了然,神奇!!!
代码如下:
class Solution {
public:
int climbStairs(int n) {
vector<int> res(n+1,0);
res[1] = 1;
res[2] = 2;
for(int i = 3; i <= n; i++)
res[i] = res[i-1] + res[i -2];
return res[n];
}
};