常用算法整理:动态规划上

本文介绍了动态规划的基本概念,强调了其与分治法的区别,并通过讲解简单的动态规划问题,如三角形路径和唯一路径,帮助理解状态定义和转移。接着讨论了中等难度的动态规划问题,如最长递增子序列、回文分割和单词拆分,展示了动态规划在解决这些问题上的应用,以及如何优化时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

什么是动态规划

动态规划是应该不能叫 一种算法,而应该叫 一类算法 或者 说是 一种思想。它和 二分查找 这种算法是不同的,二分查找我们可以用代码表示出来,并且解决所有问题的思路几乎都是一样的。而动态规划其实无法用代码表示出来,每一种问题的解决方法可能用代码写出来都不一样,所以只看动态规划的定义是很难理解的,需要拿多个题目联系才能真正理解。

动态规划的特点就是把一个大的问题分解为若干个小问题,并且这些小问题之间,每一个小问题都可通过前面的小问题计算出来。通常这些小问题其实都是一个具体的状态。如果一个问题可用动态规划解决,那么需要满足如下特点:

  1. 该问题可以分解为 dp[0], dp[1], … , dp[n] 个状态,最终的答案是其中一个状态,一般是 dp[n]。(或者dp[n][m] 等更多维度,我们这里只拿一维来说)
  2. 其中 dp[i] 可以通过 dp[0] ~ dp[i-1] 或者 `dp[i+1]~dp[n] 计算出来。

如果只看定义的话,会发现DP一定是可以通过分治法的方式来解决的。那么为什么还需通过DP算法来解决呢,因为很多时候分治法算法会有大量的重复计算,而动态规划由于记录了状态,时间复杂度会有大幅下降。很多时候时间复杂度可以从 O(2^n) 降低到 O(n^2) 。如果分治法加上一个Cache来缓存已经计算过的节点,那么他的时间复杂度和DP就是一样的了,其实 DP = DC + Cache

从上面的两个特点就可以看出来,DP 问题的难点有两个:

  1. 如果定义 dp[i],即如何拆分问题,定义状态
  2. 如何计算 dp[i],即通过之前的状态如何计算下一个状态

除了这两个难点之外,还有一点就是要处理初始值 以及可能的边界溢出问题。

另外,如果题目是要求给出所有解,肯定不用DP。DP 一般是求 最优解或者解法数。

简单的动态规划

最简单的一种动态规划,参见这一题: https://leetcode.com/problems/triangle/

这里我们用一个和题目中给出的 triangle 一样的数组 dp 来存储状态。解决上面说到的两个难点:

  1. 如果拆分问题?其实这里 dp[i][j] 就表示跳转到 triangle[i][j] 这个点所需要的最短路径。
  2. 如果计算 dp[i][j] ?dp[i][j] 其实就是取他的上层的临近节点中的比较小的一个 dp[i][j] = Math.min(last[j-1], last[j])+t[j]

然后再把边界条件处理一下,这个问题就可以解决了。代码如下:

var minimumTotal = function(triangle) {
    if(!triangle.length) return 0;
    var dp = [triangle[0]];
         //注意这里处理的初始值

    for(var i=1;i<triangle.length;i++) {
        var last = dp[i-1];
        var r
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值