最大子段和(分治法)

将长度为n的序列L划分成两个子序列,即 L(1,n/2)   和 L(n/2 + 1 , n)

 会出现3种情况:

① max{ L(1,n) } =  max{ L(1,n/2)}

② max{  L(1,n) } =  max{  L(n/2 + 1 , n) }

③ max{  L(1,n) }  = \small \sum_{k=i}^{j} a_{k}  且 \small 1 \leq i \leq n/2 ,n/2 +1 \leq j\leq n

求解子问题:对于划分阶段的情况①和②可以递归求解,情况③需要分别计算 s1 = max{  \small \sum_{k=i}}^{n/2} a_{k} } s2同理

则 s1+s2为情况三的最大子段和

合并:比较三种情况下的最大子段和,取三者最大的那个

#include<iostream>
using namespace std;

int max(int x,int y){
	return x>y?x:y;
}

int maxSum(int *nums,int left,int right){
	if(left==right)return nums[left];
	int mid=(left+right)/2;
	
	int lsum,rsum;
	lsum = maxSum(nums,left,mid); // 左边最大子段
	rsum = maxSum(nums,mid+1,right); // 右边最大子段
	
	//求中间最大子段
	int s1=0,s2=0;
	int temp=0;
	for(int i=mid;i>=left;i++){ // 注意:这里是从中间向左遍历,目的是为了让划分的左右两边序列能连接起来
		temp+=nums[i];
		if(s1<temp)s1=temp;
	}

	temp=0;
	for(int i=mid+1;i<=right;i++){
		temp+=nums[i];
		if(s2<temp)s2=temp;
	}

	int msum = s1+s2;

	return max(max(lsum,rsum),msum); 
}

int main(){
	int nums[] = {1,-5,2,3};
	cout<<maxSum(nums,0,3);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq742762377/article/details/89145182