求最大子段和——分治法
程序员文章站
2022-07-16 11:18:56
...
1、分治策略
(1)划分:按照平衡子问题的原则,将序列(a1, a2, …, an)划分成长度相同的两个子序列,则会出现以下三种情况:
(2)求解子问题:对于划分阶段的情况①和②可递归求解,情况③需要计算s1+s2:
(3)合并:比较在划分阶段的三种情况下的最大子段和,取三者之中的较大者为原问题的解。
2、示意图
3、代码实现
int maxSum(int data[], int first, int end)
{
if (first == end)
return data[first];
else
{
int sum = 0;
int mid = (first + end) / 2;
int sumLeft = maxSum(data, first, mid); //情况1
int sumRight = maxSum(data, mid + 1, end); //情况2
//情况3:
int s1 = 0, lefts = 0;
for (int i = mid; i >= first; i--)
{
lefts += data[i];
if (lefts > s1)
s1 = lefts;
}
int s2 = 0, rights = 0;
for (int i = mid + 1; i <= end; i++)
{
rights += data[i];
if (rights > s2)
s2 = rights;
}
sum = s1 + s2;
if (sumLeft > sum)
sum = sumLeft;
if (sumRight > sum)
sum = sumRight;
return sum; //情况1、2、3中,返回最大的那个
}
}
int main(int argc, char *argv[])
{
int data[20] = {0, -20, 11, -4, 13, -5, -2}; //第0个位置不用
printf("最大子段和:%d", maxSum(data, 1, 6));
system("pause");
return 0;
}
4、时间复杂度
对情况①和②,需要分别递归求解,对应情况③,两个并列for循环的时间复杂性是O(n),所以可得递推公式:
最终时间复杂度为:O(nlog2n)