假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1 阶 + 1 阶
2 阶
示例 2:
输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1 阶 + 1 阶 + 1 阶 1 阶 + 2 阶 2 阶 + 1 阶
思路:
关于动态规划的问题,一般选择先使用递归的思路切入问题。以本题为例:
- 递归的思路,我们要确定当前递归函数的定义。假设,当前我们把当前函数F(n),定义为走完n阶楼梯全部走法。下一步,我们来把它分解为子问题F(n-1)与F(n-2),分别代表走到倒数第一阶梯和倒数第二阶梯的全部走法数量。
- 在F(n-1)状态下,我们只需要走一步即可走到n,F(n-2)同理。所以问题可以提出状态转移方程:F(n) = F(n-1)+F(n-2)
- 依照上述思路,我们可以把F(n)分解为一个树形结构。即
- 状态转移方程可以写作:F(n) = F(n-1)+F(n-2)= F(n-2)+F(n-3) + F(n-3)+F(n-4)。
- 我们将对应的树形结构反过来从叶子结点开始观察。F(2) = F(1)+ F(0) 发现状态转移方程从下至上也是成立的。
- 所以我们按照状态转移方程从F(0)、F(1)带入转移方程,即可依次计算出F(n)。
- F(2) = F(1)+ F(0) FF(3) = F(2)+ F(1)。。。。。。。。。。。。。F(n-1) = F(n-2)+ F(n-3) F(n) = F(n-1)+F(n-2)
- 使用for循环即可计算出所求的F(n)
直接使用动态规划去思考确实有一定难度,如果我们使用递归的思路自上而下思考找到状态转移方程作为切入点,才是解题的方法
class Solution { public int climbStairs(int n) { int[] res = new int[n+1]; for(int i =0 ; i<res.length ; i++) res[i] = -1; res[0] = 1; res[1] = 1; for(int i = 2 ; i<= n; i++) res[i] = res[i-1] + res[i-2]; return res[n]; } }