434
社区成员
发帖
与我相关
我的任务
分享将序列a[1:n]分成长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大字段和,则a[1:n]的最大子段和有三中情形:
1.a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;
2.a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;
3.a[1:n]的最大字段和为中间段;
可用递归方法求得情形1、2。对于情形3,可以看出a[n/2]与a[n/2+1]在最优子序列中。
因此可以在a[1:n/2]中计算出s1;
在a[n/2+1:n]中计算出s2;
则s1+s2即为出现情形3时的最优值。
伪代码如下:
int maxSubSum(int a[], int left, int right){
int sum = 0;
if(left == right){
sum = a[left] > 0 ? a[left] : 0;
}
else{
int center = (left + right) / 2;
int leftSum = maxSubSum(a, left, center);
int rightSum = maxSubSum(a, center + 1, right);
int s1 = 0;
int lefts = 0;
for(int i = center; i >= left; i--){
lefts += a[i];
if(lefts > s1) s1 = lefts;
}
int s2 = 0;
int rights = 0;
for(int i = center + 1; i < right; i++){
rights += a[i];
if(rights > s2) s2 = rights;
}
sum = s1 + s2;
if(sum < leftSum) sum = leftSum;
if(sum < rightSum) sum = rightSum;
}
return sum;
}
分解子问题时间复杂度为O(1),求解子问题时间复杂度为2T(n/2),合并子问题算法时间复杂度为O(1)。
根据主定理T(n)=2T(n/2)+O(n),得到最后的时间复杂度为O(nlogn).
分治法的主要思想就是将一个问题分割为若干子问题,各子问题互相独立,子问题解决后,合并起来可以得到原问题的解。将一个复杂的且规模庞大的问题通过不断细分不断细分,变成一个个易于理解易于解决的子问题,逐一击破后合并成为最后的解。