最大子序列问题
描述:给定整数 A 1 , A 2 , ⋯ , A N A_1, A_2, \cdots, A_N A1,A2,⋯,AN (可能有负数),求 Σ k = i j A k \Sigma_{k=i}^j A_k Σk=ijAk 的最大值(如果所有整数均为负数,则最大子序列和为0)
例:
输入:-2, 11, -4, 13, -5, -2
输出:20
递归分治思想
考虑最大子序列只可能有三种可能,出现在序列的左半部分、右半部分或者跨越左右两半部分。前两种情况可以通过递归的方法实现,递归停止条件为左边界等于右边界,即只有一个数据,第三种情况可以分别计算两边的靠近中边界的最大值再相加来解决。通过比较三个数值的大小,返回最大值。
- 代码
int MaxSubSum(const int A[], int left, int right) {
int MaxLeftSum, MaxRightSum;
int MaxLeftBorder, MaxRightBorder;
int LeftBorder, RighrBorder;
int center, i;
/* 递归停止条件 */
if (left == right) {
if (A[left] > 0) {
return A[left];
}
return 0;
}
center = (left + right) / 2;
MaxLeftSum = MaxSubSum(A, left, center);
MaxRightSum = MaxSubSum(A, center + 1, right);
MaxLeftBorder = 0;
LeftBorder = 0;
for (int i = center; i > left; i--) {
LeftBorder += A[i];
if (LeftBorder > MaxLeftBorder) {
MaxLeftBorder = LeftBorder;
}
}
MaxRightBorder = 0;
RighrBorder = 0;
for (int j = center+1; j < right; j++) {
RighrBorder += A[j];
if (RighrBorder > MaxRightBorder) {
MaxRightBorder = RighrBorder;
}
}
return max(max(MaxLeftSum, MaxRightSum), MaxLeftBorder + MaxRightBorder);
//return 0;
}
动态规划
- 动态规划
时间复杂度 O(n),只扫描一次即可。
int MaxAdd::solution(const vector<int>& nums)
{
int ThisSum, MaxSum;
ThisSum = 0;
MaxSum = 0;
vector<int>::const_iterator it;
for (it = nums.begin(); it < nums.end(); it++) {
ThisSum += *it;
if (MaxSum < ThisSum) {
MaxSum = ThisSum;
}
if (ThisSum < 0) {
ThisSum = 0;
}
}
return MaxSum;
}