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
.
求和最大的子串和,我们可知子串起始位置start是0-(n-1)之间,从start开始遍历到n-1,我们可以记载下子串最大的和,所以可以写出如下代码:
public int maxSubArray(int[] nums) {
int n=nums.length;
if(n==0)
return 0;
int max = nums[0];
for(int start=0;start<n;start++)
{
int sum =0;
for(int i=start;i<n;i++)
{
sum+=nums[i];
if(max<sum)max=sum;
}
}
return max;
}
上面代码的时间复杂度是O(n^2),超时了。
我们可以创建一个sums的数组,sums[i]用来存储以i为起始位置的最大子串和,则sums[i] = max(nums[i],sums[i+1]+nums[i]),由此动态规划可写出代码:
public int maxSubArray(int[] nums) {
int n=nums.length;
if(n==0)
return 0;
int max = nums[n-1];
int[] sums =new int[n];//sums[i]用来存储以i维起始位置的最大子串和
for(int i=n-1;i>=0;i--)
{
if(i==n-1)
sums[i]=nums[i];
else
sums[i]=Math.max(nums[i]+sums[i+1],nums[i]);
max = Math.max(sums[i],max);
}
return max;
}
其实可以不用数组存,用一个变量来存取以当前位置为终止位置的最大和,那么它可以是前面和与当前数相加,或者只是当前这个数,可以有如下代码:
public int maxSubArray(int[] nums) {
int n=nums.length;
if(n==0)
return 0;
int max = nums[0];
int endsum = nums[0];//用来存放到以这个节点为终止为止的最大的和
for(int i=1;i<n;i++)
{
if(endsum>0)
endsum+=nums[i];
else
endsum = nums[i];
max = Math.max(endsum, max);
}
return max;
}