例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 为20。
1)动态规划,dp[i]中保存前i-1个数的最大和;
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
vector<int> seq;
vector<int>dp;
seq.resize(n+1);
dp.resize(n+1);
seq[0]=0;
for(int i=1;i<=n;i++)
cin>>seq[i];
int left=1,right=1;
int amount = seq[1];
dp[1] = 0;
//计算出任何子序列中的最大值
for(int i=2;i<=n;i++){
dp[i] = max(seq[i],dp[i-1]+seq[i]);
if(dp[i]>amount){
right = i;
amount = dp[i];
}
}
int sum=0;
//然后通过逆过程,找到最大值所对应的左下标
for(int i=right;i>0;i--){
sum += seq[i];
if(sum == amount){
left = i;
break;
}
}
for(int i =left;i<=right;++i)
cout<<seq[i]<<' ';
}
}
2)
int getMaxSubSum(int array[],int start,int end){
int currentSum = 0, maxSum =0;
for(int i = start;i <=end;i++){
currentSum+=array[i];
if(currentSum<=0)<span style="font-family: "Times New Roman";">//当和为负数时,抛弃</span>
currentSum= array[i];
if(currentSum>maxSum){
maxSum = currentSum;
}
}
return maxSum;
}
3)分治法(转)
#include <stdio.h>
// 方法1: 分治法
//时间复杂度 O(NlogN)
int max3(int num1 , int num2 , int num3){
int max = num1;
if(max<num2)max= num2;
if(max<num3)max=num3;
return max;
}
int maxSubSum(int array[],int start, int end){
int maxLeftSum , maxRightSum;
int maxLeftBorderSum,maxRightBorderSum;
int leftBorderSum,rightBorderSum;
int middle,i;
if(start == end){
if(array[start] >0)
return array[start];
else
return 0;
}
middle = (start+ end)/2;
//递归求解左半部分最大子序列和
maxLeftSum = maxSubSum(array, start, middle);
//递归求解右半部分最大子序列和
maxRightSum = maxSubSum(array, middle+1, end);
//求解中间部分的最大子序列和
leftBorderSum=0,maxLeftBorderSum=0;
for(i = middle;i>=start;i--){
leftBorderSum+=array[i];
if(leftBorderSum>maxLeftBorderSum)
maxLeftBorderSum = leftBorderSum;
}
rightBorderSum =0,maxRightBorderSum=0;
for (i=middle+1; i<=end; i++) {
rightBorderSum+=array[i];
if(rightBorderSum>maxRightBorderSum){
maxRightBorderSum = rightBorderSum;
}
}
return max3(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum);
}