用分治法求解最大子数组和问题

    如果仅仅是求和,可以直接使用分治+递归:

#include <stdio.h>
#define M 11
int num[M]={9,3,10,5,-6,-5,-2,-5,6,2,-4};
int search(int low,int high);
int main(void)
{
	printf("%d\n",search(0,M-1));
	return 0;
}

int search(int low,int high)
{
	if(low==high) return num[low];
	else if(low<high)
	{
		int mid = (low+high)/2;
		int left = search(low,mid);
		int right = search(mid+1,high);
		int sum=0,max=0,i=0,j=0,center=0;
		for(i=mid;i>=low;i--)
		{
			sum+=num[i];
			if(sum>max)
			{
				max = sum;
			}
		}
		center+=max;
		max = -1,sum=0;
		for(j=mid+1;j<=high;j++)
		{
			sum+=num[j];
			if(sum>max)
			{
				max = sum;
			}
		}
		center+=max;
		j = left>=right?left:right;
		j = j>=center?j:center;
		return j;
	}
} 

    如果不仅仅满足求和,进一步的想确定子数组的范围,可以封装一个结构体来确定每个子数组的范围和和,思路依然是:分治+递归

#include <stdio.h>
#define M 11

typedef struct _node{
	int left;
	int right;
	int value;
}Node;

Node search(int left,int right);
int num[M]={2,11,5,2,3,-7,-6,2,-4,6,-5};

int main(void)
{
	Node tmp = search(0,M-1);
	printf("the max value is: %d\n",tmp.value);
	printf("left is: %d    right is: %d",tmp.left,tmp.right);
	return 0;
}

Node search(int left,int right)
{
	Node tmp = {0,0,0};
	if(left==right)
	{
		tmp.left = left;
		tmp.right = right;
		tmp.value = num[left];
	} 
	else if(left<right)
	{
		int mid = (left+right)/2;
		int i=0,j=0,k=0,maxV=-1;
		Node leftN = search(left,mid);
		Node rightN = search(mid+1,right);
		Node centerN;
		for(i=mid,k=0,maxV=-999999;i>=left;i--)
		{
			k+=num[i];
			if(k>maxV)
			{
				maxV = k;
				centerN.left = i;
			}
		}
		centerN.value=maxV;
		for(i=mid+1,k=0,maxV=-999999;i<=right;i++)
		{
			k+=num[i];
			if(k>maxV)
			{
				maxV = k;
				centerN.right = i;
			}
		}
		centerN.value+=maxV;
		tmp = leftN.value>=rightN.value?leftN:rightN;
		tmp = tmp.value>=centerN.value?tmp:centerN;
	}
	return tmp;
}

猜你喜欢

转载自blog.csdn.net/qq_37437983/article/details/80424560