走阶梯问题之动态规划(java)
问题描述:
有一座高度为10级的阶梯,从下往上走,每跨一步只能向上1级或2级台阶,计算一种有多少种走法
动态规划思路:
分析最后一步:
1)从第9级一步1级走到第10级;
2)从第8级一步2级走到第10级;
3)假设从第1级到第8级有X种走法,记为F(8)
假设从第1级到第9级有Y种走法,记为F(9)
那么从第1级到第10级有X+Y种走法,也就是F(10) = F(9) + F(8);
同理:F(9) = F(8) + F(7) ...;
显然F(1)=1,F(2)=2,则可以归纳出公式:F(n)=F(n-1)+F(n-2),(n>=3,且F(1)=1,F(2)=2)。
代码实现:
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
System.out.println(getClimbingWays1(10));
Map<Integer, Integer> map = new HashMap();
System.out.println(getClimbingWays2(10, map));
System.out.println(getClimbingWays3(10));
}
/**
* 自顶向下
* 第一种实现方法
* 问题:
* 递归时会出现重复计算,计算次数是2^n,也就是时间复杂度为O(2^n).
* 比如:在计算F(4)的时候会计算一次F(3),在计算F(5)的时候也会计算一次F(3)
*/
private static int getClimbingWays1(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
return getClimbingWays1(n - 1) + getClimbingWays1(n - 2);
}
/**
* 自顶向下
* 第二种方法:递归过程中把计算的结果放到HashMap做缓存起来,计算前先判断map中是否存在值,存在则直接返回,避免重复计算。
* 时间和空间复杂度都是O(N)
*/
private static int getClimbingWays2(int n, Map<Integer, Integer> map) {
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
if (map.containsKey(n)) {
return map.get(n);
} else {
int value = getClimbingWays2(n - 1, map) + getClimbingWays2(n - 2, map);
map.put(n, value);
return value;
}
}
/**
* 自底向上
* 第三种方法:用迭代法,每一次迭代过程中只要保留前两个状态即可,比如计算F(3)=F(1)+F(2)=3, F(4)=F(2)+F(3)...
* 时间复杂度为O(N),空间复杂度为O(1)
*/
private static int getClimbingWays3(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
int a = 1;
int b = 2;
int temp = 0;
for (int i = 3; i <= n; i++) {
temp = a + b;
a = b;
b = temp;
}
return temp;
}
}