分治策略求解子数组最大并返回下标

//寻找最大子数组的和,分成三种情况来讨论
/*
在数组A[low...high]中,任何连续子数组A[i...j]的位置有三种
一、完全位于数组A[low...mid]中,因此low<=i<=j<=mid
二、完全位于数组A[mid+1...high]中,因此mid<i<=j<=mid
三、跨越了中点,因此low<=i<=mid<j<=high
*/

class FindMaxSubarray
{
public:
	//寻找跨越中点的数组,得到的是crossLow,crossHigh,crossSum
	void findMaxCrossingSubarray(int *,int,int,int);
	//寻找和最大的子数组,得到的是lLow,hHigh,sSum,
	void findMaxSubarray(int *,int,int);

	int getLow(){return lLow;}
	int getHigh(){return hHigh;}
	int getSum(){return sSum;}

private:
	int leftLow,leftHigh,leftSum;
	int rightLow,rightHigh,rightSum;
	int crossLow,crossHigh,crossSum;
	
	int lLow,hHigh,sSum;
};

void FindMaxSubarray::findMaxCrossingSubarray(int *sPtr,int low,int mid,int high)
{
	int sum=0;//临时子数组和,sum不赋值就蛋疼了!!!!!!!!!!
	
	//mid左边的最大和
	int left_sum = sPtr[mid];//最接近mid位置的数作为left_sum

	for(int k=mid;k>=low;k--)
	{
		sum = sum + sPtr[k];
		if(sum>left_sum)//寻找mid左边最大和
		{
			left_sum = sum;
			lLow = k;
		}
	}

	int right_sum = sPtr[mid+1];//最接近mid位置的数作为right_sum
	sum = 0;
	for(int k=mid+1;k<=high;k++)
	{
		sum = sum + sPtr[k];
		if(sum>right_sum)//寻找mid右边最大和
		{
			right_sum = sum;
			hHigh = k;
		}
	}
    
	//得到跨越mid的字串最大和
	sSum = left_sum + right_sum;
}


void FindMaxSubarray::findMaxSubarray(int * sPtr,int low,int high)
{
	if(low == high)//只有一个元素的起情况
	{
		lLow = low;
		hHigh = high;
		sSum = sPtr[low];
	}
	else
	{
		int mid = (low+high)/2;

		findMaxSubarray(sPtr,low,mid);//找出mid左边最大数组和
		leftLow = lLow;
		leftHigh = hHigh;
		leftSum = sSum;

		findMaxSubarray(sPtr,mid+1,high);//找出mid右边最大数组和
		rightLow = lLow;
		rightHigh = hHigh;
		rightSum = sSum;

		findMaxCrossingSubarray(sPtr,low,mid,high);//找出跨越mid的最大数组和
		crossLow = lLow;
		crossHigh = hHigh;
		crossSum = sSum;

		//比较leftSum,rightSum,crossSum的大小来确定sSum
		if((leftSum>=rightSum)&&(leftSum>=crossSum))
		{
			lLow = leftLow;
			hHigh = leftHigh;
			sSum = leftSum;
		}
		else if((rightSum>=leftSum)&&(rightSum>=crossSum))
		{
			lLow = rightLow;
			hHigh = rightHigh;
			sSum = rightSum;
		}
		else
		{
			lLow = crossLow;
			hHigh = crossHigh;
			sSum = crossSum;
		}
 	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值