【算导】分治法求解最大子数组
任意子数组必然是以下三种情况之一:
1.完全在a[low…mid]中。
2.完全在a[mid+1…high]中。
3.跨越了数组中点。
若结果为1或2,则可通过递归求解,若结果为3,则可通过一个线性时间复杂度的函数求解:
FIND-CROSS(a,low,mid,high)
leftsum=0;
sum=0;
for(int i=mid;i>=low;i--)
{
sum+=a[i];
leftsum=max(leftsum,sum);
}
rightsum=0;
sum=0;
for(int i=mid;i<high;i++)
{
sum+=a[i];
rightsum=max(rightsum,sum);
}
return leftsum+rightsum
最后写一个总函数:
FIND(a,low,high)
if(low==high)
return a[low]
else
{
mid=(low+high)/2
b=FIND(a,low,mid)
c=FIND(a,mid+1,high)
d=FIND-CROSS(a,low,mid,high)
return max(b,c,d);
}
时间复杂度O(nlogn)
一个更优化的方法,时间复杂度O(n)
从头遍历,每遍历一个数,加到sum中,与当前最大值res比较更新res,当sum小于0时,sum、
等于0,相当于把之前的所有结果清零,从下一个数重新比较并继续更新res
int maxSubArray(vector<int> nums) {
int ge = nums.size();
if (ge == 0)
return 0;
int sum = 0;
int res = nums[0];
for (int i = 0; i < ge; i++)
{
sum += nums[i];
res = max(sum, res);
if (sum < 0)
sum = 0;
}
return res;
}