求一个序列的最大字段和即求一个序列的最大连续字段和,例如[4, -3, 5, -2, -1, 2, 6, -2]的最大子段和为11=[4+(-3)+5+(-2)+(-1)+(2)+(6)]。
1.暴力算法
时间复杂度O(n^3)
求出每一个子段的和然后取最大值
#include<bits/stdc++.h>
using namespace std;
int MaxSubsequenceSum(int a[])
{
int i,j,k;
int ans;
int maxsum = 0;
for(i=0; i<8; i++) //子段起始位置
{
for(j=0; j<8; j++) //子段结束为止
{
ans = 0;
for(k=i; k<j; k++)
{
ans +=a[k];
}
if(ans>maxsum)
{
maxsum = ans;
}
}
}
return maxsum;
}
int main()
{
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
int maxSubSum = MaxSubsequenceSum(a);
cout << "The max subsequence sum of a is: " << maxSubSum << endl;
return 0;
}
2;优化后的暴力
时间复杂度(n^2)
#include<bits/stdc++.h>
using namespace std;
int MaxSubsequenceSum(int a[])
{
int i,j,k;
int ans;
int maxsum = 0;
for(i=0; i<8; i++) //子段起始位置
{
ans = 0;
for(j=i; j<8; j++) //子段结束为止
{
ans +=a[j]; //累加元素值
if(ans>maxsum) //更新最大值
{
maxsum = ans;
}
}
}
return maxsum;
}
int main()
{
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
int maxSubSum = MaxSubsequenceSum(a);
cout << "The max subsequence sum of a is: " << maxSubSum << endl;
return 0;
}
3:分治法
时间复杂度O(NlogN)
将序列分成两部分,则最大字段和可能出现在三处
1:左半部分
2:右半部分
3:横跨左右两部分,这样的情况因为有一个边界是确定的,所以只需要从中间位置向左和向右分别扫一遍,然后相加就可以
初始状态
二分递归,递归截止条件lift=right
分别求出每一段的最大字段和
右半部分也是同样的操作
最后取最大值
时间复杂度分析
#include<bits/stdc++.h>
using namespace std;
int MaxSubsequenceSum(int a[],int left,int right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
if(left==right) //递归结束条件
return a[left];
int mid = (left+right)>>1;
MaxLeftSum = MaxSubsequenceSum(a,left,mid); //左半部分
MaxRightSum = MaxSubsequenceSum(a,mid+1,right); //右半部分
MaxLeftBorderSum=0;
MaxRightBorderSum=0;
int tmpsum = 0;
for(int i=mid; i>=left; i--) // 左边包含边界最大序列和
{
tmpsum +=a[i];
if(tmpsum>MaxLeftBorderSum)
MaxLeftBorderSum = tmpsum;
}
tmpsum = 0;
for(int i=mid+1; i<=right; i++) // 右边包含边界最大序列和
{
tmpsum +=a[i];
if(tmpsum>MaxRightBorderSum)
MaxRightBorderSum = tmpsum;
}
int MaxBorderSum = MaxLeftBorderSum+MaxRightBorderSum;// // 最大边界子序列和等于两部分边界之和
return max(MaxBorderSum,max(MaxLeftSum,MaxRightSum));//返回一个最大值
}
int main()
{
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
int maxSubSum = MaxSubsequenceSum(a,0,7);
cout << "The max subsequence sum of a is: " << maxSubSum << endl;
return 0;
}
4:在线算法
时间复杂度O(N)
#include<bits/stdc++.h>
using namespace std;
int MaxSubsequenceSum(int a[],int left,int right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
if(left==right) //递归结束条件
return a[left];
int mid = (left+right)>>1;
MaxLeftSum = MaxSubsequenceSum(a,left,mid); //左半部分
MaxRightSum = MaxSubsequenceSum(a,mid+1,right); //右半部分
MaxLeftBorderSum=0;
MaxRightBorderSum=0;
int tmpsum = 0;
for(int i=mid; i>=left; i--) // 左边包含边界最大序列和
{
tmpsum +=a[i];
if(tmpsum>MaxLeftBorderSum)
MaxLeftBorderSum = tmpsum;
}
tmpsum = 0;
for(int i=mid+1; i<=right; i++) // 右边包含边界最大序列和
{
tmpsum +=a[i];
if(tmpsum>MaxRightSum)
MaxRightBorderSum = tmpsum;
}
int MaxBorderSum = MaxLeftBorderSum+MaxRightBorderSum;// // 最大边界子序列和等于两部分边界之和
return max(MaxBorderSum,max(MaxLeftSum,MaxRightSum));//返回一个最大值
}
int main()
{
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
int maxSubSum = MaxSubsequenceSum(a,0,7);
cout << "The max subsequence sum of a is: " << maxSubSum << endl;
return 0;
}