动态规划(DP)解最大连续子序列

Posted FE Tips

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划(DP)解最大连续子序列相关的知识,希望对你有一定的参考价值。

动态规划(DP)解最大连续子序列

最大连续子序列,相信大家已经在各种文章和算法题解中看到无数次这个名字了,这是一道面试中出现频率非常的题目,我在最近几年的面试中,也经常会问这道题目。

我喜欢这道题目的原因就是:从易到难可以有很多种解法,而且常见解法上也有许多可以优化的点,这种可以引导候选人更好的算法,可以根据优化点继续提问的题目是比较适合面试过程中循序渐进的沟通。
  01 . 题目

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。


示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
  02 . 思路分析

看到这道题的第一感觉是,我可以把所有可能的子数组的和全部求出来,在两层循环的过程中记录当前的最大值即可完成题目。这样的时间复杂度是O(n^2) n是数组长度

// 伪代码// 外层循环是当前子序列开始的标记for i (0 ~ arr.length)    //每次开始求一个新的子数组 当前求和归零 sum = 0    // 内层循环是当前子序列结束的标记  for j (0 ~ arr.length)    // 循环过程中进行子序列求和累加    sum += arr[j]    // 同时记录当前的最大值max    max = Math.max(sum, max)// 最终返回max即可return max   


我们有了最基础也可能是比较慢的解法,我们继续来分析是否有更好更快的解法呢(比如说让时间复杂度优化成O(n))。

我们来拆解问题,去分析相关的子序列之间的关系,然后顺着这个规律去解决这个问题。 首先我们的示例数组是[-2,1,-3,4,-1,2,1,-5,4]

  • 以数组第二个元素作为结尾的子序列最大值是1

    • [-2, 1]  sum = -1

    • [1] sum = 1

  • 以数组第三个元素作为结尾的子序列最大值是-2

    • [-2, 1, -3]  sum = -4

    • [1, -3]  sum = -2

    • [-3]  sum = -3

  • 以数组第四个元素作为结尾的子序列最大值是4

    • [-2, 1, -3, 4]  sum = 0

    • [1, -3, 4]  sum = 2

    • [-3, 4] sum = 1

    • [4] sum = 4


以此类推,我们会发现一个特点,当子序列的某个元素之前的元素和为负数时,他对后边的最大和一定是一个负向增益,没有该元素本身大。

利用这个特点,我们把目光投向整个数组,如果我们从前向后遍历,当遇到前方和为负数时,就可以抛点前边的元素,从当前元素继续向后去计算,也可以总结成一个动态规划的公式:

dp = max(dp + current, current)

当前的最优解就是取 前一个元素组合的最优解加上当前值和 当前值里更大的一个,废话不多说,我们直接上代码 (前期的题解,我都会逐行写注释,不过大家会发现我在题目分析部分其实已经把思路讲清楚了,代码只是对思路的一种计算机语言描述)

/** * @param {number[]} nums * @return {number} */let maxSubArray = function(nums) {    // 默认当前的最大和为第一个元素 let sum = nums[0]    // dp代表以当前元素结尾的最大和,默认也是第一个元素 let dp = nums[0]    // 从数组的第二个元素开始循环 for(let i = 1; i < nums.length; i++){        // 上文中提到的dp公式 dp = Math.max(dp + nums[i], nums[i])        // 同时进行当前最大值的记录 sum = Math.max(sum, dp) } return sum};

看到这,你其实已经掌握了用最简单的动态规划来解决最优解问题,它的核心就是分解问题,在子解中找到状态转移方程(上文提到的dp方程),掌握了这种方法,我们之后解决类似题目的思路就是找到转态转移方程,然后爽歪歪的翻译成js代码,再考虑下边界边界。恭喜你,这道题已经解决了!

终于把我的第一篇试水文章写完了,明天的计划是进行一下题目延伸,带着大家一起来学习《动态规划解积雨问题》,快快关注我,每天晚上来学习前端知识吧!

图片来源: leetcode 积雨问题题目描述

有什么问题、建议、意见大家都可以通过公众号和文章下方留言。我会第一时间回复的。 如果你觉得我的文章还不错,欢迎大家点赞 + 在看 + 转发到技术群和朋友圈中,如果你愿意推荐给身边的前端同学,小东更会有继续写的动力哦! 快快关注我的公众号 FE前端 哦!

文章涉及到源码已经在github中开源
请在公众号中发送“ 源码 ”获取代码地址

以上是关于动态规划(DP)解最大连续子序列的主要内容,如果未能解决你的问题,请参考以下文章

动态规划——最大连续子序列和

动态规划——总结

Leetcode-53.最大子序列和

动态规划之最大递增子序列

hdu1003 Max Sum最大连续子序列之和

486,动态规划解最大子序和