数据结构与算法--算法思维之动态规划

目录

动态规划

概念

经典问题:斐波那契数列

时间复杂度

优缺点

适用场景


 

动态规划

概念

        动态规划(Dynamic Programming),是一种分阶段求解的方法。 通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治) 的方式去解决。

        首先是拆分问题,就是根据问题的可能性把问题划分成一步一步,这样就可以通过递推或者递归来实现,关键就是这个步骤,动态规划有一类问题就是从后往前推到,有时候我们很容易知道:如果只有一种情况时,最佳的选择应该怎么做。然后根据这个最佳选择往前一步推导,得到前一步的最佳选择 然后就是定义问题状态和状态之间的关系通过前面拆分的步骤之间的关系,用一种量化的形式表现出来,类似于高中学的推导公式因为这种式子很容易用程序写出来,也可以说对程序比较亲和(也就是最后所说的状态 转移方程式) 我们再来看定义的下面的两段,我的理解是比如我们找到最优解,我们应该讲最优解保存下来,,为了往前推导时能够使用前一步的最优解,在这个过程中难免有一些相比于最优解差的解,此时我们应该放弃,只保存最优解,这样我们每一次都把最优解保存了下来,大大降低了时间复杂度。

动态规划中有三个重要概念:

  • 最优子结构
  • 边界
  • 状态转移公式(递推方程)dp方程

经典问题:斐波那契数列

        通过上边的递归树可以看出在树的每层和上层都有大量的重复计算,可以把计算结果存起来,下次再用 的时候就不用再计算了,这种方式叫记忆搜索,也叫做备忘录模式

public class fib2 {
    static int[] sub = new int[10];
    public static int fib(int n){
        if (n <= 1) {
            return n;
        }
        if (sub[n] == 0){
            sub[n] = fib(n - 1) + fib(n - 2);
        }
        return sub[n];
    }

    public static void main(String[] args) {
        System.out.println(fib(9));
    }
}

 dp方程:

if(i <  2) 则 dp[0] = 0, dp[1] = 1
if(i >= 2) dp[i] = dp[i - 1] + dp[i - 2]

最优子结构:fib[9] = fib[8] + fib[7]

边界:a[0] = 0; a[1] = 1

dp方程:fib[n] = fib[n - 1] + fib[n - 2]

public class fib3{
    public static int fib(int n){
        int a[] = new int[n + 1];
        a[0] = 0;
        a[1] = 1;
        int i;
        //a[n] = a[n - 1] + a[n - 2]
        for (i = 2; i <= n; i++) {
            a[i] = a[i - 1] + a[i - 2];
        }
        return a[i - 1];
    }

    public static void main(String[] args) {
        System.out.println(fib(9));
    }
}

使用动态规划四个步骤

  1. 把当前的复杂问题转化成一个个简单的子问题(分治)
  2. 寻找子问题的最优解法(最优子结构)
  3. 把子问题的解合并,存储中间状态
  4. 递归+记忆搜索或自底而上的形成递推方程(dp方程)

 

时间复杂度

新的斐波那契数列实现时间复杂度为O(n) 

 

优缺点

        优点:时间复杂度和空间复杂度都相当较低
        缺点:难,有些场景不适用

 

适用场景

        尽管动态规划比回溯算法高效,但是,并不是所有问题,都可以用动态规划来解决。能用动态规划解决的问题,需要满足三个特征,最优子结构、无后效性和重复子问题。在重复子问题这一点上,动态规划 和 分治算法 的区分非常明显。分治算法要求分割成的子问题,不能有重复子问题,而动态规划正好相反,动态规划之所以高效,就是因为回溯算法实现中存在大量的重复子问题。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值