题目:
假设你正在爬楼梯。需要 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 步
代码:
/**
* @作者:dhc
* @创建时间:11:06 2018/8/8
* @描述:爬楼梯
*/
public class Seventy {
//错误思路
//3ms,刷题的时候因为分类是动态规划,自然就往这面想,首先想最优子结构,
// 《《《这题求爬n阶楼梯,每次一步或者两步,n阶的爬楼梯的最高次数,那么n-m和m
//阶的楼梯的爬法的次数也应该是最多的,没啥问题,但是有个问题就是除了n-m
//加上m阶爬的方法的次数之外,还应该加上从划分的m阶楼梯到后面n-m接楼梯的爬法
// 对于m和n-m都大于2阶,有三种(从m到m+1,从m-1到m+1,从m到m+2),但是如果某一部分
// 只有一阶,则只有2中,如果两个都是1阶,即n=2,还是个特殊情况;》》》然后想的就是
//重复子问题,很明显,m阶和n-m阶中肯定存在重复子问题。然后就是自底向上的算,
//n=1,2...,。其实这是在写完后想的,并且没想明白,应该是这种最右子结构思路是错的,特此记录。
//因为分类是动态规划,就想到最优子结构性质和重复子问题,对于最右子结构想的不是很明白
//但是一想n阶的最多爬法必然包含其子问题的最多爬法应该没毛病,然后重复子问题也没啥毛病
//然后就是想看一下前面的几阶的值,想找下规律,(开始想的是result(n) = result(n-1)+2+result(n-2)+2,后来验证错误)
//求了前几个然后找出了result(n)=result(n-1)+result(n-2),而
// 这也符合重复子问题和最优子结构性质,所以。。代码如下,看了下其他人大多都是这个写法
public int climbStairs2(int n) {
int[] nums = new int[n+2];
if(n == 0){
return 0;
}
nums[1] = 1;
nums[2] = 2;
for(int i = 3;i <= n;i++){
nums[i] = nums[i-1] + nums[i-2];
}
return nums[n];
}
//2ms范例(这个用递归,感觉自顶向下有点像备忘录方法,但是递归到最后是从子问题n=1开始求,所以是动态规划)
public int climbStairs(int n) {
int[] memo = new int[n + 1];
for (int i = 0; i < n + 1; i++) {
memo[i] = -1;
}
return help(n,memo);
}
private int help(int n,int[] memo){
if (n==1 || n==0)
return 1;
if (memo[n] == -1){
memo[n] = help(n-1,memo)+help(n-2,memo);
}
return memo[n];
}
}