(1)暴力求解,运行时间是n²
int ans = -1000000;
for(int i=0; i<n; i++)
{
int sum = 0;
for(int j=i; j<n; j++)
{
sum += nums[j];
if(sum > ans)
{
ans = sum;
}
}
}
return ans;
(2)分治策略,运行时间是nlogn
使用分治技术意味着我们要将子数组划分为两个规模尽量相等的子数组,也就是找到子数组的中央位置(比如mid),然后考虑求解两个子数组A[low..mid]和A[mid+1..high]。A[low..high]的任意连续子数组A[i..j]所处的位置必然是以下三种情况之一:
(a)完全位于子数组A[low..mid]中,因此low≤i≤j≤mid
(b)完全位于子数组A[mid+1..high]中,因此mid≤i≤j≤high
(c)跨越了中点,因此low≤i≤mid≤j≤high
所以我们需要求解这三种情况的最大子数组,然后再取最大值。A[low..mid]和A[mid+1..high]可以递归求解,剩下的就是训中跨越中点的最大子数组
Find-MAX-CROSSING-SUM(a, low, mid, high)
//求中点左边的最大值和最大位置
int maxLeft;//记录左边的最大位置int maxSumLeft=-10000;//记录左边的最大和
int sumLeft=0;
for (int i = mid; i >= low; i--)
{
sumLeft += a[i];
if (sumLeft > maxSumLeft)
{
maxSumLeft = sumLeft;
maxLeft = i;
}
}
//求中点右边的最大值和最大位置
int maxRight=mid+1;//记录右边的最大位置
int maxSumRight = -10000;//记录右边的最大和
int sumRight = 0;//记录右边子数列的和
for (int i = mid+1; i <= high; i++)
{
sumRight += a[i];
if (sumRight > maxSumRight)
{
maxSumRight = sumRight;
maxRight = i;
}
}
return (maxLeft , maxRight,maxSumLeft+maxSumRight );
求解最大子数组的分治算法如下:
FIND-MAXIMUM-SUBARRAY(A, low, high)
if high==low
return (low,high,A[low])
else mid =(low+high)/2
(left-low, left-high,left-sum) = FIND-MAXIMUM-SUBARRAY(A, low, mid)
(right-low, right-high,right-sum) = FIND-MAXIMUM-SUBARRAY(A, mid+1, high)
(cross-low, cross-high, cross-sum) = Find-MAX-CROSSING-SUM(A, low, mid, high)
返回三种的最大值
(3)贪心算法,运行时间是n
将子串和为负数的子串丢掉,只留和为正的子串。
- int ans = -1000000;
- int sum = 0;
- for(int i=0; i<n; i++)
- {
- sum += nums[i];
- if(sum > ans)
- {
- ans = sum;
- }
- if(sum < 0)
- {
- sum = 0; //子串和为负数,丢掉
- }
- }
- return ans;