分3种情况,1.最大子段和可能整段在数组的左边,2.可能在数组的右边 3.也可能穿过中点先分析过中点的情况。可以先从中间元素开始向两边求出左右各自的最大子段和,然后合并,《算法导论》给出的 pseudocode 如下:
FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high)
left_sum = -∞
sum = 0
for i = mid downto low
sum = sum + A[i]
if sum>left_sum
left_sum = sum
max_left = i
right_sum = -∞
sum = 0
for j = mid+1 to high
sum = sum + A[j]
if sum>right_sum
right_sum = sum
max_right = j
return (max_left, max_right, left_sum, right_sum)
用分治法将针对于规模为n 的数组最大字段和的问题分解成规模为 n/2 ,仍然存在上述的3种情况,所以 将规模一直分解到 1.这样最大子段和就是其本身。
FIND_MAXIMUM_SUBARRAY(A, low, high)
if low = high
return (low, high, A[low])
else
mid = floor((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)
return (left_low, left_high, left_sum)
else if right_sum>=left_sum and right_sum>=cross_sum
return (right_low, right_high, right_sum)
else
return (cross_low, cross_high, cross_sum)

FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high)
left_sum = -∞
sum = 0
for i = mid downto low
sum = sum + A[i]
if sum>left_sum
left_sum = sum
max_left = i
right_sum = -∞
sum = 0
for j = mid+1 to high
sum = sum + A[j]
if sum>right_sum
right_sum = sum
max_right = j
return (max_left, max_right, left_sum, right_sum)
用分治法将针对于规模为n 的数组最大字段和的问题分解成规模为 n/2 ,仍然存在上述的3种情况,所以 将规模一直分解到 1.这样最大子段和就是其本身。
FIND_MAXIMUM_SUBARRAY(A, low, high)
if low = high
return (low, high, A[low])
else
mid = floor((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_SUBARRAY(A,low,mid,high)
if left_sum>=right_sum and left_sum>= cross_sumreturn (left_low, left_high, left_sum)
else if right_sum>=left_sum and right_sum>=cross_sum
return (right_low, right_high, right_sum)
else
return (cross_low, cross_high, cross_sum)
The time complexity is O(nlgn).
# include <iostream>
# include <cmath>
using namespace std;
struct maximum_subarray{
int index_low;
int index_high;
int max_sum;
};
maximum_subarray find_cross_max_sub(int a[], int low, int mid, int high);
maximum_subarray find_max_sub(int a[],int low,int high);
int main(){
int a[16] = {13, -3, 20, -25, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
maximum_subarray m_s;
m_s = find_max_sub(a, 0, 15);
for(int i = 0; i< 16; ++i)
cout<<a[i]<<" ";
cout<<endl;
cout<<"The maximum subarray ";
for(i = m_s.index_low; i<=m_s.index_high; ++i)
cout<<a[i]<<" ";
cout<<endl;
cout<<"The sum of maximum subarray "<<m_s.max_sum<<endl;
return 0;
}
maximum_subarray find_cross_max_sub(int a[],int low, int mid, int high){
int left_sum = -999; //保证所有字段和都大于它
int sum = 0, max_left = 0;
for(int i = mid; i>= low; i--){
sum = sum + a[i];
if(sum > left_sum){
left_sum = sum;
max_left = i;
}
}
int right_sum = -999;
int max_right = 0;
sum = 0;
for(int j = mid+1; j<= high; j++){
sum = sum + a[j];
if(sum > right_sum){
right_sum = sum;
max_right = j;
}
}
maximum_subarray cross_m_s;
cross_m_s.index_low = max_left;
cross_m_s.index_high = max_right;
cross_m_s.max_sum = left_sum+right_sum;
return cross_m_s;
}
maximum_subarray find_max_sub(int a[], int low, int high){
int mid;
maximum_subarray m_s0;
m_s0.index_low = low; m_s0.index_high = high; m_s0.max_sum = a[low];
maximum_subarray m_s1, m_s2, cross_m_s;
if(low == high)
return m_s0;
else{// divide and conquer
mid = floor((low+high)/2);
m_s1 = find_max_sub(a,low, mid);
m_s2 = find_max_sub(a,mid+1,high);
cross_m_s = find_cross_max_sub(a,low,mid,high);
}
if(m_s1.max_sum>=m_s2.max_sum && m_s1.max_sum>=cross_m_s.max_sum)
return m_s1;
else if(m_s2.max_sum>=m_s1.max_sum && m_s2.max_sum>=cross_m_s.max_sum)
return m_s2;
else
return cross_m_s;
}
