最大连续子序列和

来源:互联网 发布:软件行业人才需求 编辑:程序博客网 时间:2024/04/24 19:05

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;}



0 0