分治法 最大子数组

内容来自《算法导论》第四章
假定我们要寻找子数组A[low…high]的最大数组,使用分治法意味着我们要将子数组划分成两个规模尽量相等的子数组A[low…mid]和A[mid+1…high],所以最大数组的所处位置一定是在一下三种情况中:
1、完全位于子数组A[low…mid]中,因此low<=i<=j<=mid
2、完全位于子数组A[mid+1…high],因此mid 3、跨越了中点,因此low<=i<=mid<=j<=high

代码如下

#include
#define INF 9999999
struct node{
	int left;
	int right;
	int sum;
};
struct node FMCS(int A[], int low, int mid, int high){
	int leftSum = -INF;
	int sum = 0;
	int maxLeft = mid;
	for(int i=mid;i>=low;i--){//从中点向左找到一个最大的数组和,重点是一定要从中点开始
		sum = sum+A[i];
		if(sum > leftSum){
			leftSum = sum;
			maxLeft = i;
		}
	}
	int rightSum = -INF;
	sum = 0;
	int maxRight=mid+1;
	for(int i=mid+1;i<=high;i++){//从中点开始向右找一个最大的数组
		sum = sum+A[i];
		if(sum > rightSum){
			rightSum = sum;
			maxRight = i;
		}
	}
	//两个循环的结果,找到跨越中点的一个最大的子数组
	//重点是跨越中点,先满足跨越中点,再找最大
	struct node result;
	result.left = maxLeft;
	result.right = maxRight;
	result.sum = leftSum + rightSum;
	return result;
}
struct node FMS(int A[], int low, int high){
	if(high == low){
		struct node result;
		result.left = low;
		result.right = high;
		result.sum = A[low];
		return result;
	}
	else{
		int mid = (low + high) / 2;
		struct node left,right,cross;
		//1、完全位于子数组A[low...mid]中,因此low<=i<=j<=mid
		left = FMS(A,low,mid);
		//2、完全位于子数组A[mid+1...high],因此mid
		right = FMS(A,mid+1,high);
		//3、跨越了中点,因此low<=i<=mid<=j<=high
		cross = FMCS(A,low,mid,high);
		if(left.sum >= right.sum && left.sum >= cross.sum)
			return left;
		else if(right.sum >= left.sum && right.sum >= cross.sum)
			return right;
		else
			return cross;
	}
}

你可能感兴趣的:(算法模板,算法导论,分治法)