题目:
输入样例:
6
-2 11 -4 13 -5 -2(结尾无空行)输出样例:
20(结尾无空行)
主函数:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int MaxSubseqSum1(vector<int>List, int N);//算法1
int MaxSubseqSum2(vector<int>List, int N);//算法2
int MaxSubseqSum3(vector<int>List, int N);//算法3
int MaxSubseqSum4(vector<int>List, int N);//算法4
int main()
{
int sum, x, i;
vector<int>List;
scanf("%d",&sum);
for(i=0;i<sum;i++){
scanf("%d",&x);
List.push_back(x);
}
printf("%d ",MaxSubseqSum1(List,sum)); //算法1
printf("%d ",MaxSubseqSum2(List,sum)); //算法2
printf("%d ",MaxSubseqSum3(List,sum)); //算法3
printf("%d ",MaxSubseqSum4(List,sum)); //算法4
return 0;
}
算法1:穷举所有最大子列和,从中找出最大值。算法复杂度是 O(N^3).
int MaxSubseqSum1(vector<int>List, int N)
{
int ThisSum, MaxSum = 0;
int i, j, k;
for(i=0; i<N; i++){ //i是子列左端
for(j=i; j<N; j++){ //j是子列右端
ThisSum = 0; //List[i]到List[j]的子列和
for(k=i; k<=j; k++){
ThisSum += List[k];//每次循环都是从头加数,只需要每次累加1项即可
}
if(ThisSum > MaxSum)
MaxSum = ThisSum;//更新最大子列和
}
}
return MaxSum;
}
算法2:对算法1的改进,降低了算法复杂度。算法复杂度是O(N^2);
int MaxSubseqSum2(vector<int>List, int N)
{
int ThisSum, MaxSum = 0;
int i, j;
for(i=0; i<N; i++){ //i是子列左端
ThisSum = 0;
for(j=i; j<N; j++){ //j是子列右端
ThisSum += List[j];//只需累加即可
if(ThisSum > MaxSum)
MaxSum = ThisSum;//更新子列和
}
}
return MaxSum;
}
算法3:分而治之。
如果把原始序列一分为二,那么最大子列和有以下三种情况:
1.左半边;2.右半边;3.横跨中间的一段;
算法思想:
1.将序列中分为左右两个序列;
2.递归求出两个子列的最大和“S左”“S右”;
3.从中分点向左,右两边扫描,找出横跨分界线的最大子列和“S中”;
4.最大子列和为左右子列“S左”和“S右”与横跨的子列和“S中”的最大值;
int Max3(int A, int B, int C)
{
return A>B ? (A>C ? A : C) : (B>C ? B : C); //返回A,B,C中的最大值;
}
int DivideAndConquer(vector<int>List, int left, int right)
{
int MaxLeftSum, MaxRightSum;
int MaxLeftBorderSum, MaxRightBorderSum;
int LeftBorderSum, RightBorderSum;
int center, i;
if(left == right)//递归的终止条件
{
if(List[left] > 0) return List[left];
else return 0;
}
//下面是“分”的过程
center = (left + right)/2;//找中间点
//递归求得两边子列的最大和
MaxLeftSum = DivideAndConquer(List, left, center);
MaxRightSum = DivideAndConquer(List, center + 1, right);
//下面求得跨分界线的最大子列和
MaxLeftBorderSum = 0; LeftBorderSum = 0;
for(i=center; i>=left; i--){
LeftBorderSum += List[i];
if(LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}//左边扫描结束
MaxRightBorderSum = 0; RightBorderSum = 0;
for(i=center+1; i<=right; i++){
RightBorderSum += List[i];
if(RightBorderSum > MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}//右边扫面结束
//下面返回“治”的结果;
return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);
}
int MaxSubseqSum3(vector<int>List, int N)
{
return DivideAndConquer(List, 0, N-1);
}
算法4:在线处理。
//算法4:在线处理
int MaxSubseqSum4(vector<int>List, int N)
{
int i;
int ThisSum, MaxSum;
ThisSum = MaxSum = 0;
for(i=0; i<N; i++){
ThisSum += List[i]; //向右累加
if(ThisSum > MaxSum)
MaxSum = ThisSum; //发现更大和则更新当前结果;
else if(ThisSum < 0) //如果当前子列和为负;
ThisSum = 0; //则不可能使后面的部分和增大,抛弃之;
}
return MaxSum;
}