原题:
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
第一次看到这个题,我擦,又一个动态规划,好,先直接来个最简单的给服务器来点压力,没想到,我猜对了,超时了。。。。不过思想应该可行,如下:设一个函数,求n个台阶已经走了前k个时的所有可能number,那么在这种情况下只能有两种选择,走一步或者走两步,而且这个时候可选的可能性就是走一步后剩余情况和走2步剩余情况的和。。。。
虽然超时,but,只要加个备忘就哦了么(自顶向下的方法)。。。。
超时代码:
class Solution {
public:
int climbStairs(int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
return number (0 , n);
}
//共n个台阶,前k个已经决定了策略,总共的爬楼梯可能
int number (int k, int n){
if ( k == n-2 ) return 2;
if ( k == n-1 ) return 1;
else return number( k+1 , n ) + number ( k+2 , n);
}
};
正确的思路:加一个备忘录,这是动态规划自顶向下的标准算法之一
由于从上面的代码看到number(k,n)中调用了number(k+1,n),于是定义一个数组record来记录number(k,n),主要有一个需要注意的地方,也是递归最难的部分,就是判定什么时候返回,这个题比较简单,只有两种情况
1 k==n-1时,即离终点只有一个台阶时,只能有一种可能
2 k==n-2时,即离终点有两个台阶时,有两种可能
代码如下:
class Solution {
public:
int climbStairs(int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int record [n];
//先初始化一下
for (int i = 0 ;i < n ; i++){
record[i]= -1;
}
return number (0 , n , record);
}
//共n个台阶,前k个已经决定了策略,总共的爬楼梯可能
int number (int k, int n , int record [] ){
if(record[k] >= 0){
return record[k];
}
int result = 0;
if ( k == n-2 ) {
//return之前保存一下,距离终点只有2个台阶,有2种可能
result = 2;
}
else if ( k == n-1 ){
//return之前保存一下,距离终点只有1个台阶,有一种可能
result = 1;
}
else {
result = number( k+1 , n , record) + number ( k+2 , n ,record) ;
}
record[k] = result;
return result;
}
};
动态规划也可以利用自底向上。。。。