题目:https://pta.patest.cn/pta/test/15/exam/4/question/709
#include <iostream>
using namespace std;
int MaxSubseqSum2(int A[], int N);
int MaxSubseqSum3(int A[], int left, int right); //(数组名,元素左起0,元素终点n-1)
int MaxSubseqSum4(int A[], int N); //(数组名, 元素个数)
int main()
{
int n;
cin >> n;
// int numSeq[n]; //C++是不支持用变量初始化数组的
int numSeq[100000];
for(int i=0; i<n; i++){
cin >> numSeq[i];
}
// int maxSum = MaxSubseqSum4(numSeq, n);
int maxSum = MaxSubseqSum3(numSeq, 0, n-1);
if(maxSum< 0) {
maxSum = 0;
}
cout<<maxSum<<endl;
return 0;
}
// 算法2 穷举法
int MaxSubseqSum2(int A[], int N){
int ThisSum, MaxSum = 0;
int i, j, k;
for(i=0; i<N; i++){ //i是子列左端位置
ThisSum = 0; //ThisSum是从A[i]到A[j]的子列和
for(j=i; j<N; j++){ //j是子列右端位置
ThisSum += A[j];
//对于相同的i,不同的j,只要在j-1次循环的基础上累加1项即可
if(ThisSum > MaxSum) //如果刚得到的这个子列和更大
MaxSum = ThisSum; //则更新结果
} //j循环结束
} //i循环结束
return MaxSum;
}
int compareThreeNums(int a, int b, int c){
return a>b ? (a>c?a:c) : (b>c?b:c) ; //if a>b: then if a>c, else if b>c
}
// 算法3 分而治之
int MaxSubseqSum3(int A[], int left, int right){
int leftMax, rightMax;
//如果list中只剩一个元素了,则left==right
if(left == right){
return A[left];
}
//list不只一个元素,二分+治之 递归,获得左右最大
int middle = (left + right) / 2;
leftMax = MaxSubseqSum3(A, left, middle);
rightMax = MaxSubseqSum3(A, middle+1, right);
//寻找跨越边界的最大
// int tempLeftMax, leftBorderMax = 0; //未显式赋值,造成错误假内容
// int tempRightMax, rightBorderMax = 0;
int tempLeftMax = 0, leftBorderMax = 0;
for (int i = middle; i >= left; i--){
tempLeftMax += A[i];
if(tempLeftMax > leftBorderMax){
leftBorderMax = tempLeftMax;
}
}
int tempRightMax = 0, rightBorderMax = 0;
for (int i = middle+1; i <= right; i++){
tempRightMax += A[i];
if(tempRightMax > rightBorderMax){
rightBorderMax = tempRightMax;
}
}
int middleMax = rightBorderMax + leftBorderMax;
int maxSum = compareThreeNums(middleMax, leftMax, rightMax);
return maxSum;
}
// 算法4 在线方法/动态规划
int MaxSubseqSum4(int A[], int N){
int maxSum, thisSum = 0;
int i = 0;
for(i = 0; i<N; i++){
thisSum += A[i]; /* 向右累加 */
if(thisSum > maxSum){
maxSum = thisSum; /* 发现更大和则更新当前结果 */
} else if (thisSum < 0){ /* 如果当前子列和为负 */
thisSum = 0; /* 则不可能使后面的部分和增大,抛弃之 */
}
}
//此题里,不需要记录最大和的具体项,发现新最大立刻更新,当前和已经小于0时,则加后面的大项必然可以大过加已有的负数
return maxSum;
}