LeetCode-Climbing Stairs

看到这个觉得这个问题应该是一个经典问题。

于是就想通过动态规划,从最后一步开始,不断递归解决问题,于是用很短的代码就把这个实现了。但是。。发现如果数字太大(到 44),因为复杂度太高(应该是 2^n),算法直接超时,所以还需要继续改进。

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

因为在递归的过程中,可能会计算很多类似的结果,所以可以将一些结果进行缓存,需要的时候直接查表,击败了 33.37%的人。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int climb(int n,int[] store){
if(n<=2)
return n;
else{
if(store[n-1]>0)
return store[n-1];
else{
int stepCount=climb(n-1,store)+climb(n-2,store);
store[n-1]=stepCount;
return stepCount;
}

}
}
public int climbStairs(int n) {
int[] store=new int[n];
return climb(n,store);
}
}

看了官方 Solution 以后,大概明白动态规划还可以正着写(手动捂脸),只要知道之前的步骤的结果,就可以知道后面的结果。所以可以像斐波那契数列一样,定下前两个,根据stair[n]=stair[n-1]+stair[n-2]这个递推公式从前往后进行计算。(当然,更作弊的方法就是直接用斐波那契数列的求和公式,这里就没必要写出代码了)

其实这个方法和上面方法的复杂度一样,所以耗时也基本类似。(当然使用这个方法可以进一步去掉数组,只用两个变量代替,这样更加降低了算法的空间占用)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int climbStairs(int n) {
if(n==1)
return 1;
int[] stair=new int[n+1];
stair[1]=1;
stair[2]=2;
for(int i=3;i<=n;i++){
stair[i]=stair[i-1]+stair[i-2];
}
return stair[n];
}
}