枚举法
#include<iostream>
#define N 10
using namespace std ;
int main()
{
int A[N] = {1,3,-5,2,6,-7,8,1,0,-1};
int best = A[0];
for(int i = 0 ; i < N ; i++){
for(int j = i; j < N ; j++){
int sum = 0 ;
for(int k = i ; k <= j ;k++){
sum+=A[k];
}
if(sum > best ) best = sum;
}
}
cout<<best;
return 0 ;
}
这种方法是依次计算出所有的和进行比较
第一次取第一个数
第二次取第一个和第二个数
直到第一个到第n个,然后从第二个开始
走遍了所有情况
时间复杂度为O(n³)
2进行分析后对枚举法进行改进
#include<iostream>
#define N 10
using namespace std ;
int main()
{
int best = 0 ;
int A[10] = {1,3,-5,2,6,-7,8,1,0,-1};
int s[11];
s[0] = 0 ;
for(int i = 1 ; i <= N ; i++){
s[i] = s[i-1]+A[i];
}
for(int i = 0 ; i < N ; i++){
for(int j = i ; j < N ; j++){
best = best>s[j]-s[i-1] best:s[j]-s[i-1];
}
}
cout<<best;
return 0 ;
}
先计算出从第一个数到第n个数的和
然后用从第一个数到第n个数的和 减去第一个数到第m个数的和可求得m到n的和
进行比较后也可得出正确结果
时间复杂度为O(n²)
3分治法
#include<iostream>
#define N 10
using namespace std;
int maxsum(int *A , int x , int y );
int main()
{
int best = 0 ;
int A[N] = {1,3,-5,2,6,-7,8,1,0,-1};
best = maxsum(A,0,N);
cout<<best;
return 0 ;
}
maxsum(int *A , int x , int y ){
if( y – x == 1 ) return A[x]>0 A[x]:0;
int m = x+ (y-x)/2;
int maxsum1 = maxsum(A,x,m);
int maxsum2 = maxsum(A,m,y);
int maxsum3 = 0 ;
int sum = 0 ;
for(int i = m-1 ; i >= 0 ;i–){
sum+=A[i];
if(sum > maxsum3 ) maxsum3 = sum;
}
int maxsum4 = 0 ;
sum = 0 ;
for(int i = m ; i < y ;i++){
sum+=A[i];
if(sum > maxsum4 ) maxsum4 = sum;
}
maxsum3+=maxsum4;
int max = 0 ;
if(maxsum1>max) max = maxsum1;
if(maxsum2>max) max = maxsum2;
if(maxsum3>max) max = maxsum3;
return max ;
}
再次分析后发现 将数组分为左右两边
和最大子序列在左边 右边 或者中间跨左右
于是可分而治之 从中间分开 递归到只剩两个数时 返回他们的和最大子序列
即左边,右边,或者二者相加到最后将三个数进行比较可得到和最大子序列
此时时间复杂度为O(n*logn)
4 在线处理
#include<iostream>
#define N 10
using namespace std ;
int main()
{
int A[N] = {1,3,-5,2,6,-7,8,1,0,-1};
int ThisSum , MaxSum;
int i ;
ThisSum = MaxSum = 0 ;
for(i = 0 ; i < N ;i++ ){
ThisSum += A[i];
if(ThisSum > MaxSum) MaxSum = ThisSum;
else if(ThisSum < 0 ) ThisSum = 0 ;
}
cout<<MaxSum;
return 0 ;
}
从左到右进行寻找
设置当前和为0 最大和为0
加上下一个数时会出现三种情况
大于最大和 那么将最大和的值赋为当前和
小于最大和但当前和大于0 那么就有可能在加上下一个数时大于最大和 所以将当前和赋值为加上后的值 但最大和不变
小于最大和并且当前和小于0 最大和依旧不变,但是将当前最大和赋值为0,因为负数无论加什么数都会让那个数变小
此时时间复杂度变成了O(n)