算法篇 - 动态规划问题
原创
©著作权归作者所有:来自51CTO博客作者Jaemon的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目
有一座高度是10级台阶的楼梯, 从下往上走, 每跨一步只能向上1级或者2级台阶. 要求用程序来求出一共有多少种走法
公式推导
1: [1]
= 1 种
2: [1,1],[2]
= 2 种
3: [1,1,1],[1,2],[2,1]
= 3 种
4: [1,1,1,1],[2,1,1],[1,2,1],[1,1,2],[2,2]
= 5 种
5: [1,1,1,1,1],[2,1,1,1],[1,2,1,1],[1,1,2,1],[1,1,1,2],[2,2,1],[2,1,2],[1,2,2]
= 8 种
…
n: f(n) = f(n - 1) + f(n - 2)
逆向推导
假设楼梯有 n 阶, 则一共有 f(n) 种走法。 假设此时站在第 n 阶往下走
- 第一次跨一步只跨1个台阶, 则剩余 n - 1 阶台阶共有 f(n - 1) 种走法
- 第一次跨一步只跨2个台阶, 则剩余 n - 2 阶台阶共有 f(n - 2) 种走法
即:f(n) = f(n - 1) + f(n - 2)
方式1 - 递归实现
public class AnswerApp {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
BigDecimal fn = f(100);
System.out.println("fn: " + fn);
long endTime = System.currentTimeMillis();
System.out.println("execute time " + (endTime - startTime) / 1000 + " s.");
}
public static BigDecimal f(int n) {
if (n < 0) {
return new BigDecimal(0);
} else if (n == 1 || n == 2) {
return new BigDecimal(n);
} else {
return f(n - 1).add(f(n - 2));
}
}
}
方式2 - 递归+备忘录实现
public class AnswerApp {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
BigDecimal fn = f(100, new HashMap<>());
System.out.println("fn: " + fn);
long endTime = System.currentTimeMillis();
System.out.println("execute time " + (endTime - startTime) / 1000 + " s.");
}
public static BigDecimal f(int n, HashMap<Integer, BigDecimal> cache) {
if (n < 0) {
return new BigDecimal(0);
} else if (n == 1 || n == 2) {
return new BigDecimal(n);
} else {
if (cache.containsKey(n)) {
return cache.get(n);
}
BigDecimal rlt = f(n - 1, cache).add(f(n - 2, cache));
cache.put(n, rlt);
return rlt;
}
}
}
推荐使用:
递归+备忘录, 原因: 引入缓存,极大的增强了算法的计算效率