题外话:本文原文是之前在知乎专栏写的一篇文章,现在读来发现好多地方没有写清楚,所以现在做了些修改,希望把分析过程说的更明白一些。为什么要发布到慕课网来呢,主要是因为个人认为这里的IT氛围更好更专业。

正文:

最近看到的一道编程题目:有一个数组,如1, -5, 8, 3, -4, 15, -8,查找其中连续和最大的相邻串的值。在本例中,最大值为8 + 3 + -4 + 15 = 22.

这道题最容易想到的算法就是暴力搜索:第一遍从数组第一个元素开始搜索整个数组,记录连续和的最大值;第二遍从数组第二个元素开始搜索整个数组,以此类推找到最大连续子序列和,下面看看go代码:

package main

import (

"fmt"

)

func calculateMaxSumOfSubArray(a []int) int {

maxSum := a[0]

n := len(a)

for i := 0; i

sum := 0

for k := i; k

sum += a[k]

if sum > maxSum {

maxSum = sum

}

}

}

return maxSum

}

func main()  {

arr := []int{1, -5, 8, 3, -4, 15, -8}

fmt.Println("max sum is:", calculateMaxSumOfSubArray(arr))

}

这个算法简单粗暴,但有性能问题,总共需要n + (n - 1) + (n - 2) + ... + 1次访问数组元素,也就是时间复杂度是O(n*n)。那么有没有更好的算法呢?

很多高手拿到这个题目的第一反应就是很简单啊,动态规划思想很容易搞定,但也有同学像我一样不懂动态规划啊,难道要去先学一下吗?不,我们先分析看看能不能有啥思路。

首先假设我们已经找到了最大连续和子串在数组中的起始位置(i)和结束位置(j),其中i <= j,即最大和maxSum = a[i] + a[i + 1] + ... + a[j],我们来看看这个子串有什么性质:1,a[i] > 0,否则我们完全可以去掉a[i]这个元素 而得到一个更大的和;

2, i > 0且a[i - 1] < 0 或 i == 0,下面假设i > 0,这一条性质也是因为如果a[i - 1] > 0的话我们求和时可以加上a[i - 1]这个元素得到一个更大的和;

3, 元素a[i - 1]与它之前的任一元素之间的子串之和sum < 0 ,即对于任何一个m(0 <= m < i - 1),则有a[m] + a[m + 1] + ... + a[i - 1] < 0,这条性质同样可以用反证法证明。

如果一下想不明白上面的第三条性质,可以在纸上用笔画画图看看。根据第二三条性质,我们感觉 a[i - 1]是一个分界点,最大和的子串要么就在a[i - 1]元素之后,要么就在a[i - 1]之前,最大和的子串不可能跨过a[i - 1]这个点。仔细用笔画画图想一下为什么,还是用前面的反证来思考。下面举2个例子来看看:

1,假设数组为 1,-2, 3, 4,5,很容易发现-2这个元素满足前述的第二个和第三个性质:

-2 本身是负数;

-2 + 1 = -1 < 0

所以-2是这样一个分界点,最大和的字串要么在-2之后要么在之前,-2之前的和是1,之后的和sum = 3 + 4 + 5 = 12,所以这个字串的最大和为12;

我们稍微改变一下数组的元素就可以看到最大和字串在分解点之前的情况:

2,假设数组为 100,-101, 3, 4,5,很容易发现-101这个元素满足前述的第二个和第三个性质:

-101 本身是负数;

-101 + 100 = -1 < 0

所以-101是这样一个分界点,最大和的字串要么在-101之后要么在之前,-101之前的和是100,之后的和sum = 3 + 4 + 5 = 12,所以这个字串的最大和为100;

根据前面的分析我们可以得出结论:只要找到分解点 a[i - 1],最大和的子串要么就在a[i - 1]元素之后,要么就在a[i - 1]

之前,最大和的子串不可能跨过a[i - 1]这个点;一个数组中可能有多个这种分界点,

但每个分界点都可以把前后完全分开,可以单独算分界点之间的最大和,然后在这些最

大和之间取最大值。

假设对于数组a,我们找到了两个分界点a[i]和a[j],那么整个数组的最大字串和就是max(sum(a[0]...a[i-1]), sum(a[i+1]...a[j-1]), sum(a[j+1]...a[len-1]))

那么怎么去找这个分界点呢?我们从前面的第三个性质可以看出如果a[i-1]是分界点,那么a[0]到a[i - 1]之和必定为负数,所以我们就从a[0]开始逐个往后求和,为了便于描述我们把这个和记为sum,sum第一次变成负数时就是我们要找的分界点。可能您会说sum(a[0]...a[i-1])<0并不代表sum(a[m]...a[i-1])<0 (m < i -1)呀?看看找这个分界点的方法,我们是从第一个元素开始求和,分界点是当sum第一次变成负数时找到的元素,也就是说a[0]到a[m-1]之和必定大于0,记为sum1, a[m]到a[i-1]之和记为sum2, 于是有关系sum1 + sum2 = sum < 0 推出sum2 = sum - sum1 < 0.

分析到这里算法基本上就出来了,下面给出go代码:func calculateMaxSumOfSubArray2(a []int) int {

maxSum := a[0]

sum := a[0]

for i := 1; i

sum += a[i]

if sum

sum = 0

} else {

if sum > maxSum {

maxSum = sum //记录最大和

}

}

}

return maxSum

}

最大子序列求和_最大连续子序列和相关推荐

  1. c 最大子序列和_最大连续子序列

    最大连续子序列:是指序列中所有子序列中元素和最大的一个 例如{-2,11,-4,13,-5.-2}中最大连续子序列为{11,-4,13}其和为20 若所有k个元素都为负数,则定义其最大和为0,输出整个 ...

  2. 最大子序列求和_连续子序列最大和与乘积问题的分析

    问题描述 给定(可能是负的)整数序列A1, A2,...,AN, 寻找(并标识)使Sum(Ak)(k >=i, k <= j)的值最大的序列.如果所有的整数都是负的,那么连续子序列的最大和 ...

  3. 最大子序列求和_最大子序列和问题

    问题描述: 给定一个整数序列,a0, a1, a2, -- , an(项可以为负数),求其中最大的子序列和.如果所有整数都是负数,那么最大子序列和为0: 例如:对于序列-2, 11, -4, 13, ...

  4. php 求最大连续子序列,[HDOJ 1003]动态规划法求和最大的连续子序列

    Case 1: 14 1 4 Case 2: 7 1 6 题目的大致意思就是要你从给定的数组中找出一段连续的子序列,使得这段连续的子序列中所有数字的总和不小于数组中其他任何一段连续子序列中数字的总和. ...

  5. 最大子序列求和_最大子序列和问题  一步一步到最优

    在<数据结构和算法分析 C++描述>上看到了一个例子.看过之后,我就在想,这是怎么一步一步的递推出来的,想了好长时间,才整理成这篇博文. 问题描述: 给定一个整数序列,a0, a1, a2 ...

  6. 最大子序列求和_算法——求最大子段和

    一.问题描述 给定由n个整数组成的序列(a_1,a_2,-,a_n),最大子段和问题要求该序列形如 的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0. 例如,序列(-20, ...

  7. 【ACM】 1231 最大连续子序列

    [1231 最大连续子序列 ** Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

  8. 【恋上数据结构】动态规划(找零钱、最大连续子序列和、最长上升子序列、最长公共子序列、最长公共子串、0-1背包)

    动态规划(Dynamic Programming) 练习1:找零钱 找零钱 - 暴力递归 找零钱 - 记忆化搜索 找零钱 - 递推 思考题:输出找零钱的具体方案(具体是用了哪些面值的硬币) 找零钱 - ...

  9. 2019 蓝桥杯省赛 B 组模拟赛(一) J. 程序设计:蒜厂年会 环形连续子序列求和问题

    题目描述 在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 n 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币.但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币.因为这些数字都是可见的,所 ...

最新文章

  1. ExtJs_关于combobox的那些分页二三事
  2. 中两个查询结果相减_MySQL 在查询结果中插入伪行
  3. 服务器返回值 解释 ajax提交方式 后台数据刷进前端
  4. linux qtcreator输入中文,新版QT creator下解决fcitx无法输入中文问题(QTcreatorV4.1.0)...
  5. GL 与 CV 管线 (pipeline) 比较与相互转换
  6. 首届!「中国云计算基础架构开发者大会」征稿启动
  7. Mac墨刀怎么导出HTML,mockingbot墨刀中文使用说明.pdf
  8. Win10访问不了Samba网络共享的原因以及解决办法
  9. MQ 消息队列问题整理
  10. 医院各领域榜单。22个科室、100种常见疾病
  11. 根号二怎么不用计算机算,[转载]开根号,不用计算器你会么?
  12. C语言二叉排序树的中序遍历,C语言实现二叉树的中序线索化及遍历中序线索二叉树...
  13. 堕落了!经典软件下载网站被查
  14. 深入解析Tensor索引中的Indexing Multi-dimensional arrays问题
  15. 高德地图有用的API
  16. buuctf刷题记录(6)
  17. ChatGPT国内在线版、微信版
  18. CMake I 设置编译器标志
  19. windows内核情景分析 --- DPC 目的信令点编码
  20. 大咖来了!今年的 COSCon 主论坛你可以见到这些大咖

热门文章

  1. CentOS7在/etc/grub2.conf引导中配置1G大页内存
  2. 51单片机18B20测温1602LCD显示
  3. linux内核驱动之 设备驱动简介之内核划分
  4. Python组合数据类型:序列sequence,列表list、元组tuple
  5. python3 format函数_【Python3 第三日】%和format格式化输出 函数
  6. RecycleVier的简单实现
  7. vue ui框架_Vue移动端UI框架指南
  8. 第三只眼使用局域网版本还是网络版好_让汽车的“第三只眼”更聪明更安全
  9. linux+性能排查,Linux系统性能排查基础
  10. mac连接局域网mysql_MySQL for Mac 安装和基本操作