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.
1、有一点点像暴力法,但是加了很多条件。利用sumtemp和sumMax分别保存当前和和当前最大和。如果当前和为负数,则更新为0,移动指针重新判断,也就是新的元素不需要加上之前这些负数,同时为了避免全都是负数,所以sumMax是要更新的。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if (nums.size() == 0)
return 0;
int sumtemp = 0;
int sumMax = nums[0];
for (int first = 0; first<nums.size(); first++)
{
sumtemp += nums[first];
if (sumtemp>sumMax)
sumMax = sumtemp;
if (sumtemp<0) //加起来变大了,但是仍然是负数。重新更新sum
{
sumtemp = 0;
continue;
}
for (int last = first + 1; last<nums.size(); last++)
{
sumtemp += nums[last];
if (sumtemp>sumMax)
sumMax = sumtemp;
if (last==nums.size()-1 )
return sumMax;
if (sumtemp < 0)
{
sumtemp = 0;
last = nums.size();
break;//break跳出的是if。而不是跳出last,所以直接给last赋值。
}
}
sumtemp = 0;
//********************************************
//其实可以思考下,如果last到了最后而不是由强行赋值为nums.size的话,就可以结束了。于是加入23-24行
}
return sumMax;
}
};
2、分治法
https://blog.csdn.net/xiao_ren_wu_/article/details/78180036
二分,计算前最大,计算后最大,计算前连续的最大值和后连续的最大值,得到中间连续的那段最大值,比较这三者。
int getMaxNum(int a,int b,int c){
if (a > b&&a > c){
return a;
}
if (b > a&&b > c){
return b;
}
return c;
}
int maxSumRec(int data[], int left, int right){
if (right - left == 1){
//如果当前序列只有一个元素
return data[left];
}
int center = (left + right) / 2;//计算当前序列的分裂点
int maxLeftSum = maxSumRec(data,left,center);
int maxRightSum = maxSumRec(data,center,right);
//计算左边界最大子序列和
int leftBonderSum = 0;
int maxLeftBonderSum = data[center-1];
for (int i = center - 1; i >= left; i--){
leftBonderSum += data[i];
if (maxLeftBonderSum < leftBonderSum){
maxLeftBonderSum = leftBonderSum;
}
}
//计算右边界最大子序列和
int rightBonderSum = 0;
int maxRightBonderSum = data[center];
for (int i = center; i < right; i++){
rightBonderSum += data[i];
if (maxRightBonderSum < rightBonderSum){
maxRightBonderSum = rightBonderSum;
}
}
//返回当前序列最大子序列和
return getMaxNum(maxLeftBonderSum + maxRightBonderSum, maxLeftSum, maxRightSum);
}
3、动态规划
递归思想:
C[i+1]=max{C[i]+A[i+1],A[i+1]};
C[1]=A[1] 若A[1]>0 否则C[1]=0
代码就不写了,来个伪代码
sum<min
b<-0 //b是前一个最大子段和
for i<-1 to n do
if b>0
then b<- b+A[i]
else b<-A[i] //重新赋值
if b>sum
then sum<-b
c<-i //记录最大和的末标号
return sum,c
子段起始位置还需要另外算。