问题描述:
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [?2,1,?3,4,?1,2,1,?5,4],
the contiguous subarray [4,?1,2,1] has the largest sum = 6.
问题分析(参考了算法导论第4章分治策略的内容):
为求一个含负数的一组数种,和为最大的子数组
这里使用分治的思想
首先,这一个子数组它只可能以3种方式存在:
完全在上半部分:low--mid
完全在下半部分:mid--high
或者跨越中点地存在:可理解为Arr[i..mid]+[mid+1..j]最大的元素和组成
算法的思想:递归地寻求左、右部分的最大子数组和
最后合并每次递归结果的解(只保留最后最大的结果)
时间复杂度分析:
n=1 T(1)=Θ(1)
n>1 子问题——求解左子数组和右子数组;每组子问题求解花费T(n/2)
所以算法的运行时间T(n)递归式为:
T(n)={ Θ(1) ,n=1
2T(n/2) ,n>1
最后可以求解出T(n)=Θ(nlgn)
1 #include<iostream> 2 #include<climits> 3 using namespace std; 4 const int infinite=-9999; 5 int Find_Max_Crossing_Subarray(int arr[],int low,int mid,int high)//扫描上半部分最大和、下半部分最大和,上下部分结合为跨越中点最大和 6 { 7 8 int left_sum=infinite; 9 int right_sum=infinite; 10 int max_left=-1,max_right=-1,sum=0; 11 for(int i=mid; i>=low; i--) 12 { 13 sum+=arr[i]; 14 if(sum>left_sum) 15 { 16 left_sum=sum; 17 max_left=i; 18 } 19 } 20 sum=0; 21 for(int j=mid+1; j<=high; j++) 22 { 23 sum+=arr[j]; 24 if(sum>right_sum) 25 { 26 right_sum=sum; 27 max_right=j; 28 } 29 } 30 return (left_sum+right_sum); 31 } 32 int Find_Maximum_Subarray(int arr[],int low,int high)// 33 { 34 if(high==low)//只有一个元素的时候 35 return arr[low]; 36 else 37 { 38 int mid=(low+high)/2; 39 int leftSum=Find_Maximum_Subarray(arr,low,mid); 40 int rightSum=Find_Maximum_Subarray(arr,mid+1,high); 41 int crossSum=Find_Max_Crossing_Subarray(arr,low,mid,high); 42 if(leftSum>=rightSum&&leftSum>=crossSum) 43 return leftSum; 44 else if(rightSum>=leftSum&&rightSum>=crossSum) 45 return rightSum; 46 else return crossSum; 47 } 48 } 49 int main() 50 { 51 int arr[10]= {5,2,8,-6,9,1,10,7,-13,9}; 52 int ans=Find_Maximum_Subarray(arr,0,9); 53 cout<<ans<<endl; 54 return 0; 55 }