//寻找最大子数组的和,分成三种情况来讨论
/*
在数组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;
}
}
}
分治策略求解子数组最大并返回下标
最新推荐文章于 2021-05-21 10:28:20 发布