1.O(n^2)
基本思路 对所有的情况进行遍历 , 对其实地点i进行遍历 ,为N , 对终止地址j进行遍历 ,为N ,对i到j之间的内容进行累加求和 , 为N 所以能为O(n^3)的解法 ,但是在进行对i到j之间的累加的时候有 sum[i,j]=sum[i,j-1]+a[j]
所以可以压缩到O(n^2)
# include <stdio.h>
int n;
int a[500];
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int sumi=0,sumj=0;
int maxsum = -9999999;
for(int i=0;i<n;i++){
int sum=0;
for(int j=i;j<n;j++){
sum+=a[j];
if(sum>maxsum){
maxsum = sum;
sumi = i;
sumj = j;
}
}
}
printf("最大的连续子序列为 : %d\n",maxsum);
printf("起始位置为 %d 终止为止为 %d\n",sumi+1,sumj+1);
}
return 0;
}
2. dp方法 从后向前考虑一下 对于最后一个数 有三种情况 第一个是让他自己成为最大连续子序列 a[n-1] 第二种是 让以a[n-1] 结尾的序列成为最大连续子序列 记为end[n-1] 第三种是a[n-1] 根本就没有包括在最大连续子序列里面 所以就没有他的事 记为all[n-2]
所以在初始化过程中就可以记end[0] = all[0] = a[0]
然后从1开始遍历 得到一个O(n)的解决方案
# include <stdio.h>
int n;
int a[500];
int end[500];
int all[500];
int max(int a,int b){
return a>b?a:b;
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
all[0] = end[0] =a[0];
for(int i=1;i<n;i++){
end[i]=max(end[i-1]+a[i],a[i]);
all[i]=max(all[i-1],end[i]);
}
printf("%d\n",all[n-1]);
}
return 0;
}
在这之中可以记录一下连续最大子序列的初始位置和最终的位置
也可以有此推出另一种O(n)的方法
# include<stdio.h>
int n;
int a[500];
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int sum = 0;
int maxsum = -99999;
int beginsum,endsum;
for(int i=0;i<n;i++){
if(sum>=0){
sum+=a[i];
}else{
sum = a[i];
beginsum = i;
}
if(sum>maxsum){
maxsum = sum;
endsum = i;
}
}
printf("%d %d %d\n",maxsum,beginsum,endsum);
}
return 0;
}
3. 如果存在环的话
max(不允许存在环的情况下的最大连续子序列,所有序列的总和减去最小连续子序列的值(转换为对偶问题))
# include<stdio.h>
int n;
int a[500];
int maxsum_limited(){
int sum =0;
int maxsum = -999;
for(int i=0;i<n;i++){
if(sum<0){
sum = a[i];
}else {
sum+=a[i];
}
if(sum>maxsum){
maxsum = sum;
}
}
return maxsum;
}
int maxsum_unlimited(){
int total =0;
int sum=0;
int minsum =99999;
int maxsum_li = maxsum_limited();
if(maxsum_li<0){
return maxsum_li;
}
for(int i=0;i<n;i++){
if(sum>0){
sum = a[i];
}else{
sum+=a[i];
}
if(sum<minsum)
minsum = sum;
total += a[i];
}
return maxsum_li>(total-minsum)?maxsum_li:(total-minsum);
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int sum = 0;
int maxsum = -99999;
printf("%d\n",maxsum_unlimited());
}
return 0;
}