动态规划(Dynamic Programmaing ,简称DP)
通过把原问题分解为相对简单的子问题的方式求解复杂的方法。动态规划尝尝适用于有重叠问题和最优子结构性质的问题。
将原问题拆成若干个子问题,同时保存子问题的答案,使得每个子问题只求解一次,这样把一个复杂问题分阶段进行简单化,逐步化简成简单问题。大大节省了时间和空间。
动态规划算法的两种形式
动态规划的核心是记住已经求过的解,记住求解的方式有两种:
1.自顶向下的备忘录法
2.自底向上
举例来引入动态规划
求斐波拉契实例Fibonacci
1.先用递归来实现这个算法
public int fib(int n){
if(n <= 0)
return 0;
if(n == 1)
return 1;
rerurn fib( n - 1) + f(n - 2);
}
递归算法的执行流程如下,假如输入6,执行的递归数如下:
上述的递归数中每一个节点都会执行一次,很多节点被重复执行fib(2)被执行了5次,由于每调用一次函数的时候都要保留上下文,所以会用到大量空间。比如fib(2)被执行了这么多次,若在在执行时把执行过的子节点保存起来,后面若要在用到的时候就直接调用就能节约大量的时间。
- 下面是用动态规划来解决斐波拉契数列问题
public class 斐波那契数列 {
public static int fib(int n) {
if (n == 0 || n == 1) {
return 1;
}
int r1 = 1;
int r2 = 1;
int result = 0;
for (int i = 2; i <= n; i++) {
result = r1 + r2;
r1 = r2;
r2 = result;
}
return result;
}
动态规划还是利用了递归思想,上面的算法不管么执行,在计算fib(6)的时候最后总要算出fib(5),fib(4),fib(1),n
而动态规划的思想是先算出fib(1),fib(2)…,利用数组保存了先计算的值,后面的执行可直接调用,这样了时间和空间上的困扰,这是动态规划的核心,先计算出子问题,在由子问题解决父问题。