背(fei)景(hua):
书接上回,自从张小胖同学成功AC了Leetcode 1.两数之和这道题后,便觉得自己特别牛批。这天,他又信心满满地来到了Leetcode题库,准备大战一番。这时,一行“最长子序列和”突然映入张小胖的眼帘:
题目描述:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [2,-4,3,-1,2,-4,3],
输出: 4
解释: 连续子数组 [3,-1,2] 的和最大,为 4。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
题解:
题目难度:简单
解题思路:
“最长子序列和?”小胖不禁嘴角上扬。要知道,这道题可是一道超级经典的入门题。只见小胖稍加思索,心中便已经有了主意。
//方法一:暴力法 时间复杂度:O(n^3)
func maxSubArray(nums []int) int {
max := -2147483647
var sum int
for l := 0 ; l<len(nums) ; l ++ {
for r := l ; r<len(nums) ; r ++ {
for t := l ; t<=r ; t ++{
sum+=nums[t]
}
if sum > max {
max = sum
}
sum = 0
}
}
return max
}
“既然是求最长子列和,那么我只要列举出主列中的所有子列,并找出所有子列和的最大值不就可以了?”小胖得意地彪呼呼地交了上去。突然,一道光芒刺瞎了小胖的狗眼:
果不其然超时了,时间复杂度高达O(n^3)的暴力算法就是不一般,果然没有经受住Leetcode测评姬的考验 。小胖骂骂咧咧地看着题目中的测试样例,陷入了沉思。
2、-4、3、-1、2、-4、3 //答案4(选3、-1、2)
“我们看到这行数列,确实能够轻松地推出它的最大子列和是4,那么答案是怎么推出来的呢?”小胖边想,边把推理过程写了下来:
首先看到第一个数,是2,2后面是-4,所以如果-4是最优子列的一部分,那么2一定也在其中(答案就增加了)
随后是3,如果3把前面的2和-4加上去,结果是1。这个时候反而比原来的3要小了。所以如果答案含有3,就一定不会加上前面的2和-4。
下一个数是-1。这个数加上前面的3之后增加了数值(变成了2),所以如果答案有-1,辣么绝对还有前面的3。
接下来是2,如果2加上前面的序列(3、-1),辣么它的值变为4。比原先增加了。
然后是-4,如果把-4加上前面的序列(3、-1、2),结果会变成0,比原先的-4大,所以如果-4是答案的一部分,那么前面的三个数也一定是答案的一部分。
最后一个数,也就是3,如果将3加上前面的序列,结果变成了3。最后我们来看一看刚推导的结果,发现4是我们可以得出的最大和,故输出4。
如果针对此题,我们便不难发现以下推论:
第一个数为一个有效序列。如果一个数加上上一个有效序列得到的结果比这个数大,那么该数也属于这个有效序列(接纳这个数进入有效序列)。 如果一个数加上上一个有效序列得到的结果比这个数小,那么这个数单独成为一个新的有效序列(上一个有效序列完全拖后腿,所以直接抛弃掉)。
“推导完毕。“小胖长舒一口气,感叹道:”原来我们的大脑在不知不觉中运用了动态规划的思想。那还等什么,俺滴键盘已经迫不及待了!”说罢小胖哗哗一顿乱敲:
//方法2:动态规划法,时间复杂度O(n)
func maxSubArray(nums []int) int {
if len(nums) < 2 {
return nums[0]
}
var temp int
res := -2147483647
for i := 0 ; i < len(nums); i ++ {
if nums[i] > temp + nums[i] {
temp = nums[i]
} else {
temp = temp+nums[i]
}
if temp > res {
res = temp
}
}
return res
}
终于AC了,小胖露出了欣慰的笑容。
所谓动态规划,就是把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解的过程。在本样例中,我们正是利用了动态规划的思想,把求解长度为7的主列中最大子列和的问题转化为求解一条长度为1的主列中最大子列和的问题,时时刻刻让当前状态的局部子列和处于最优,并不断扩充主列长度,直至长度为7。换句话说,我们如果在第6个数、第5个数…第n个数就停下来的话,那时所求得的最大子列和依然是对于前n个数的最优解!这恰恰说明动态规划思想满足‘最优化原理’和‘无后效性’的特性。
PS:关于题目中所提到的分治法,各位读者朋友有思路了吗?
本文引用博客链接:https://www.luogu.com.cn/blog/Walker-68145/solution-p1115
原题目链接:https://leetcode-cn.com/problems/maximum-subarray