赞
踩
给定由 n 个整数(可能为负整数)组成的序列,求解其连续的最大字段和。当所有数都是负整数时,最大字段和是 0 .
如:a[] = {-2, 11, -4, 13, -5, -2}时, max = 11 + (-4) + 13 = 20.
将所给序列a[1:n] 分成a[1:n/2] 和 a[n/2 + 1 : n]两个部分,则最大值有一下三种情况:
对应前两种情况利用递归可以直接求出,而第三种情况可以从中间部分向两边蔓延(直到找到的数是负数为止)
时间复杂度为:nlogn
int maxSubSum(int *a, int left, int right) { if (left == right) { return a[left] < 0 ? 0 : a[left]; } int centor = (left + right) / 2; int leftSum = maxSubSum(a, left, centor); int rightSum = maxSubSum(a, centor + 1, right); int s1 = 0; int lefts =0; for (int i = centor; i >= left; i--) { // 从中点向左找最大字段和 lefts += a[i]; if (lefts > s1) { s1 = lefts; } } int s2 = 0; int rights = 0; for (int i = centor + 1; i <= right; i++) {//从中点向右找最大字段和 rights += a[i]; if (rights > s1) { s1 = rights; } } int sum = s0 + s1; // 第三种情况的最大子段和 sum = max(sum, leftSum); // 求解三种情况的最大值 sum = max(sum, rightSum); return sum; } int maxSum(int *a, int n) { return sumSubSum(a, 1, n); // 可以根据数组a自行调整 }
用一个数组b[],b[j]表示以从位置 j 开始向前找一段的最大子段和,当b[j - 1] > 0时, b[j] = b[j-1] + a[j] , 当 b[j-1] 小于0的时候,b[j] = a[j],即动态方程为b[j] = max( b[j - 1] + a[j], a[j]). 最后结果为 数组b的最大值
算法实现:
int maxSum(int *a, n) {
int sum = 0, b = 0;
for (int i = 0; i < n; i++) {
if (b > 0) {
b += a[i]
} else {
b = a[i];
}
if (b > sum) {
sum = b; // 存储之前计算的最大值
}
}
return sum;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。