最大子数组和

最大子数组和
Zyx_2012情景导入
有时,我们需要求一个数组的最大子数组和(即连续子数组的和最大),并给出这个和(别问为什么,问就是题目要)。
Kadane 算法的原理
首先,我们获得一个数组,并定义两个变量 csum
和 smax
。
然后,我们可以开始 kadane 算法。
在算法开始时,将 csum
(当前连续子段的和)初始化为数组的第一个元素,将 smax
(全局最大子段和)也初始化为该值。
接下来,从第二个元素开始,依次向右遍历整个数组。
对于每一个元素 a[i]
,我们要判断:
如果当前的 csum
加上 a[i]
小于 a[i]
( csum
小于 0),说明前面的子段对总和是负贡献,继续加下去只会让后续的结果更小,所以应当舍弃之前的子段,从当前位置重新开始,也就是令 csum = a[i]
。
否则,如果 csum
仍然大于等于 0,就说明它对后续仍有正向贡献,我们可以安全地把当前元素加上去,csum += a[i]
。
每处理完一个元素,就更新全局最大值:smax = max(smax, csum)
。
这样,smax
始终保存着从开头到当前位置为止出现过的最大连续子段和。
当遍历完整个数组后,smax
就是整个数组的最大连续子段和。
换句话说,Kadane 算法的核心思想是:
只要当前子段的和为负,就立即丢弃,从当前位置重新开始。
它把一个看似需要枚举所有区间的问题,优化成了线性时间的动态更新过程。
视频(点击观看):
示例题目
【题目描述】
给定一个只包含
'0'
和'1'
的字符串,你可以选择恰好一个连续子串,将其中的字符全部反转(即'0'
变'1'
,'1'
变'0'
)。
你的任务是,在最多一次这样的操作之后,使得整个字符串中'1'
的数量尽可能多。输出操作后
'1'
的最大可能数量。
【输入格式】
一行,一个长度为
n (1 ≤ n ≤ 2×10^5)
的字符串,只包含字符'0'
和'1'
。
【输出格式】
一个整数,表示翻转后
'1'
的最大数量。
样例
【样例输入 1】
1 110001【样例输出 1】
1 6【样例解释 1】
原本有 3 个
'1'
。
翻转中间的"000"
→"111"
,变为"111111"
,此时共有 6 个'1'
,但我们不能再优化了。
输出6
。
【样例输入 2】
1 1111【样例输出 2】
1 4【样例解释 2】
原本全是
'1'
,翻转任何一段都会减少'1'
,所以最优是不操作。
【数据范围与提示】
- 1 ≤ n ≤ 200000
- 字符仅含
'0'
和'1'
暴力做法
1 |
|
这种做法的时间复杂度是 O(n³)
,数据一大就 T 了
kadane 做法
1 |
|
注释已经写得非常明确了,有不懂的可以在评论区提出疑问,我看到后会尽量在第一时间解答