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
.
More practice:
O(n)的解法有很多,第一种,判断当前数该不该加,如果加上当前数和比当前数大,加上当前数,否则用当前数替换。动起来的代码如下:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
public class Solution {
public int maxSubArray(int[] nums) {
int currAdd = 0, max = Integer.MIN_VALUE;
for (int num:nums) {
currAdd = Math.max(currAdd + num, num);
max = Math.max(currAdd, max);
}
return max;
}
}
第二种,贪心算法,如果把nums[n]都换成nums[n] + nums[n-1],会得到一个sum的折线图,找最大和substring,也就是找折线图的最大差。代码如下:
public class Solution {
public int maxSubArray(int[] nums) {
int sum = 0, max = Integer.MIN_VALUE, min = 0;
for (int num:nums) {
sum += num;
if (sum - min > max) {
max = sum - min;
}
if (sum < min) {
min = sum;
}
}
return max;
}
}
那么该想
Divide and Conquer了,无非是二分查找,mid有三种情况:
1、substring在mid左边
2、substring在mid右边
3、substring横跨mid
明白这点,就可以写代码了:
public class Solution {
public int maxSubArray(int[] nums){
int maxV = Integer.MIN_VALUE;
return maxArray(nums, 0, nums.length - 1, maxV);
}
public int maxArray(int[] A, int left, int right, int maxV)
{
if(left>right)
return Integer.MIN_VALUE;
int mid = (left+right)/2;
int lmax = maxArray(A, left, mid -1, maxV);
int rmax = maxArray(A, mid + 1, right, maxV);
maxV = Math.max(maxV, lmax);
maxV = Math.max(maxV, rmax);
int sum = 0, mlmax = 0;
for(int i= mid -1; i>=left; i--)
{
sum += A[i];
if(sum > mlmax)
mlmax = sum;
}
sum = 0; int mrmax = 0;
for(int i = mid +1; i<=right; i++)
{
sum += A[i];
if(sum > mrmax)
mrmax = sum;
}
maxV = Math.max(maxV, mlmax + mrmax + A[mid]);
return maxV;
}
}