Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
solution1 optimization problem -DP
- optimization problem -DP
- the format of the sub problem(or the state of each sub problem).
- recursive
maxSubArray(A, i) = maxSubArray(A, i - 1) > 0 ? maxSubArray(A, i - 1) : 0 + A[i];
动态规划。用循环做。
F(i)=numsi;
F(i)=nums[i]+F(i-1)(F(i-1)>0)
细节:nums只有{-1}时,所以开始sum=nums[0],然后从第二个开始循环。
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.empty())
return 0;
int cur=array[0];
int max=cur;
for(auto it = array.begin()+1;it!=array.end();it++)
{
if(cur<=0)
{
cur = *it;
}
else
{
cur+=*it;
}
if(cur>max)
{
max=cur;
}
}
return max;
}
};
solution2 Divide-and-Conquer
- The Divide-and-Conquer algorithm breaks nums into two halves and find the maximum subarray sum in them recursively.
- the maximum subarray spans the two halves.
- a linear algorithm: starting from the middle element and move to both ends (left and right ends), record the maximum sum we have seen. In this case, the maximum sum is finally equal to the middle element plus the maximum sum of moving leftwards and the maximum sum of moving rightwards.
- Since we are done with LHS and RHS, we only need to check the case where we pass the middle element.(i.e. the middle element must be included).In that case, since our question asks a continuous subset, it must expand that way.
分治法。2*O(n/2)+O(1)=O(n)
- divide:用递归来分别求左右子集的max
- merge:用dp来从左右分别线性探索,加上mid
- 最后找到divide和merge中最大的就是要求的值。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return maxSubArray(nums, 0, nums.size() - 1);
}
private:
int maxSubArray(vector<int>& nums, int l, int r) {
if (l > r) {
return INT_MIN;
}
//divide:
int m = l + (r - l) / 2;
int lmax = maxSubArray(nums, l, m - 1);//left
int rmax = maxSubArray(nums, m + 1, r);//right
int partmax = max(lmax, rmax);//not including mid
//Merge:
int ml= 0,mr = 0;
//left-DP:O(n/2)
for (int i = m - 1, sum = 0; i >= l; i--) {
sum += nums[i];
ml = max(sum, ml);
}
//right-DP:O(n/2)
for (int i = m + 1, sum = 0; i <= r; i++) {
sum += nums[i];
mr = max(sum, mr);
}
//Merge-including mid,for continuous subset:O(1)
int contmax=ml + mr + nums[m];
return max(partmax,contmax);
//2*O(n/2)+O(1)=O(n)
}
};
Kadane’s algorithm
- Aka Maximum Sum of Subarray
- Dynamic Programming
Maximum Subarray Problem
From Wikipedia
In computer science, the maximum subarray problem is the task of finding the contiguous subarray within a one-dimensional array, a[1…n], of numbers which has the largest sum.
The task is to find a subarray (contiguous elements) of the given array that has the largest sum. For instance:
[1, 5, -1, 0, 10]
The answer would be 15
or the entire array (it’s also a subarray)
[0, -1, -5, 0, -4]
The answer would be 0
and so on.
Solutions
Brute-force
All you need is going through all sub-arrays, keep the global maximum and compare.
Dynamic Programming (Kadane’s Algorithm)
O(n)
runtime complexityO(1)
space.
Following function shows the Kadane’s algorithm implementation which uses two variables, one to store the local maximum and the other to keep track of the global maximum:
def max_subarray(A):
max_ending_here = max_so_far = A[0]
for x in A[1:]:
max_ending_here = max(x, max_ending_here + x)
max_so_far = max(max_so_far, max_ending_here)
return max_so_far
So we assume that the largest subarray is the first element, then we go through A[1:]
elements (all elements except the first one).
At each step, what we do is:
- Can current element plus the last largest sum_ help to find a largest subarray (line 4)?
- If yes, update the
max_ending_here
or our local maximum, otherwise current element is the largest subarray (array of one). - Then update the global maximum or
max_so_far
if there is a new global maximum.
When the loop is over, return the global maximum.
Conclusion
Kadane’s algorithm is a Dynamic Programming approach to solve “the largest contiguous elements in an array” with runtime of O(n).