求最大子陣列的三種方法
(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;