题目:
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
最大连续子序列和,非常经典的题。
当我们从头到尾遍历这个数组的时候,对于数组里的一个整数,它有几种选择呢?它只有两种
选择:1、加入之前的 SubArray;2. 自己另起一个 SubArray。那什么时候会出现这两种情况呢?
如果之前 SubArray 的总体和大于 0 的话,我们认为其对后续结果是有贡献的。这种情况下我们
选择加入之前的 SubArray
如果之前 SubArray 的总体和为 0 或者小于 0 的话,我们认为其对后续结果是没有贡献,甚至是
有害的(小于 0 时) 。这种情况下我们选择以这个数字开始,另起一个 SubArray。
设状态为 f[j],表示以 S[j] 结尾的最大连续子序列和,则状态转移方程如下:
f[j] = max{f[j − 1] + S[j],S[j]}, 其中1 ≤ j ≤ n
target = max{f[j]}, 其中1 ≤ j ≤ n
解释如下:
• 情况一,S[j] 不独立,与前面的某些数组成一个连续子序列,则最大连续子序列和为
f[j − 1] + S[j]。
• 情况二,S[j] 独立划分成为一段,即连续子序列仅包含一个数 S[j],则最大连续子序列和为
S[j]。
其他思路:
• 思路 2:直接在 i 到 j 之间暴力枚举,复杂度是 O(n 3 )
• 思路 3:处理后枚举,连续子序列的和等于两个前缀和之差,复杂度 O(n 2 )。
• 思路 4:分治法,把序列分为两段,分别求最大连续子序列和,然后归并,复杂度 O(nlogn)
• 思路 5:把思路 2O(n 2 ) 的代码稍作处理,得到 O(n) 的算法
• 思路 6:当成 M=1 的最大 M 子段和
动态规划:
1 class Solution { 2 public: 3 int maxSubArray(vector<int>& nums) { 4 int result = INT_MIN, f = 0; 5 for (int i = 0; i < nums.size(); ++i) { 6 f = max(f + nums[i], nums[i]); 7 result = max(result, f); 8 } 9 return result; 10 } 11 };