动态规划、动态规划、动态规划!!!!
假设你正在爬楼梯。需要 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 阶
解答:
采用递归模拟人爬楼梯。当输入44的时候,超出时间限制了。
class Solution {
public static int walk(int step, int m, int n) {
int a = step + m;
if (a == n) return 1;
else if (a > n) return 0;
return walk(1, a, n) + walk(2, a, n);
}
public static int climbStairs(int n) {
return walk(1, 0, n) + walk(2, 0, n);
}
}
发现走法的总数等于sum=Cn0+Cn−11+…Cmmsum=C_n^0+C_{n-1}^1+…C_m^msum=Cn0+Cn−11+…Cmm,结果到n=44的时候与结果预期不同,其原因可能是计算中的舍入误差。
class Solution {
public static int Compent(int m, int n) {
if (n == 0) return 1;
int sum = 1;
for (int i = 1; i <= n; i++){
sum = sum * m / i;
m--;
}
return sum;
}
public static int climbStairs(int n) {
int m = n / 2;
int sum = 0;
for (int i = 0; i <= m; i++) {
sum = sum + Compent(n, i);
n--;
}
return sum;
}
}
看了别人的解法。爬楼梯问题其实类似于斐波那契数列。
c[n]=c[n−1]+c[n−2]c[n] = c[n-1] +c[n-2]c[n]=c[n−1]+c[n−2] ,即当前路数等于前一步的路数加上前两步的路数。
class Solution {
public static int climbStairs(int n) {
if (n == 0) return 1;
if (n == 1) return 1;
return climbStairs(n - 1) + climbStairs(n - 2);
}
}
用斐波那契数列的方法还是超时,改用动态规划后通过了。
class Solution {
public static int[] a = new int[50];
public static int climbStairs(int n) {
if (n == 0) return 1;
if (n == 1) return 1;
if (a[n] != 0) return a[n];
return a[n] = climbStairs(n - 1) + climbStairs(n - 2);
}
}
其原因是递归实现斐波那契需要遍历一个完全二叉树,而采用动态规划记录了每一次新产生的值(a[2],a[3],a[4]等),减少了遍历的次数。