最大连续和问题 Java

问题
给出一个长度为n的序列A1,A2,…,An,求最大连续和。
即:求找到1<= i <= j <=n,使得Ai+…+Aj尽量大。
以下代码以 数组A[n+1] 的值都等于下标为例
分析:
最简单的方法就是枚举每个子串,求出和最大的子串。

    int best=A[1];
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                int sum=0;
                for(int begin=i;begin<=j;begin++){
                    sum+=A[begin];
                    if(best>sum)best=sum;
                }
            }
        }
        System.out.println(best);

时间复杂度是n的三次方,只能处理小数据

下面尝试进行优化
可以考虑用前缀和来把时间复杂度优化为n的平方
因为连续子序列之和等于两个前缀和之差
求子序列的和直接用S[j]-S[i-1]即可 省去了一个循环
这里的max函数是求两个数中最大的一个,代码省略

S[0]=0;
        int best=0;
        for(int i=1;i<=n;i++){
            S[i]=S[i-1]+i;
        }
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                best=max(best,S[j]-S[i-1]);
            }
        }
        System.out.println(best);

用分治法来处理
时间复杂度为n*logn

 static int n;
    static int[] A;
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        A=new int[n+1];
        for(int i=1;i<=n;i++){
            A[i]=i;
        }
        int ans=split(A,1,n+1);
        System.out.println(ans);
    }
    //返回数组在左闭右开区间[x,y)中的最大连续和
    static int split(int[] A,int x,int y){
        int v,L,R,maxs;
        if(y-x==1)return A[x]; //只有一个元素,直接返回
        int mid=x+(y-x)/2;    //分治第一步:划分成[x,mid)和[mid,y)
        maxs=max(split(A,x,mid),split(A,mid,y));//分治第二步:递归求解
        v=0;L=A[mid-1];  //分治第三步:(合并1) 从分界点开始往左的最大连续和L
        for(int i=L;i>=x;i--){
            L=max(L,v+=A[i]);
        }
        v=0;R=A[mid];   //分治第三步:合并(2) 从分界点开始往右的最大连续和R
        for(int i=R;i<y;i++){
            R=max(R,v+=A[i]);
        }
        return max(maxs,L+R);   //把子问题的解与L和R比较
    }
    static int max(int a,int b){
        return a<b?b:a;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值