最大子序列和

最大子序列和

给定(可能有负的)整数A1,A2,…,AN,求子序列和的最大值。
例如:对于输入-2,11,-4,13,-5,-2,答案为20(从A2到A4)

法1:穷举所有的可能

时间复杂度为

O(n^{3})
 public static int maxSubSum1(int a[]){
        int max=0;
        for (int i=0;i<a.length;i++){
            for (int j=i;j<a.length;j++){
                int s=0;
                for (int k=i;k<=j;k++){
                    s+=a[k];
                }
                if (s>max){
                    max=s;
                }
            }
        }
        return max;
    }
法2:撤销一个for循环来避免三次的运行时间

时间复杂度为

O(n^{2})
public static int maxSubSum2(int a[]){
        int max=0;
        for (int i=0;i<a.length;i++){
            int s=0;
            for (int j=i;j<a.length;j++){
                s+=a[j];
                if (s>max){
                    max=s;
                }
            }
        }
        return max;
    }
法3:使用分治法,先分别计算出左半部分、右半部分的最大子序列和,然后计算出跨越中间部分的最大子序列和,求三个中的最大值即可。

时间复杂度为

O(nlogn)
//分治法
    public static int maxSubSum3(int a[],int left,int right){
        int max=0;
        if (left==right){
            if (a[left]>0)
                return a[left];
            else
                return 0;
        }
        int mid=(right+left)/2;
        int l=maxSubSum3(a,left,mid);//求左半部分的最大子序列和
        int r=maxSubSum3(a,mid+1,right);//求右半部分的最大子序列和
        /*求跨越中间元素的最大子序列和,
        左边的从中间元素向左计算,右边的从中间元素的下一个元素向右计算
        */
        int maxLeftBorderSum=0;
        int leftBorderSum=0;
        for (int i=mid;i>=left;i--){
            leftBorderSum += a[i];
            if (leftBorderSum>maxLeftBorderSum)
                maxLeftBorderSum=leftBorderSum;
        }
        int maxRightBorderSum=0;
        int rightBorderSum=0;
        for (int i=mid+1;i<=right;i++){
            rightBorderSum += a[i];
            if (rightBorderSum>maxRightBorderSum)
                maxRightBorderSum=rightBorderSum;
        }
        int max_lr=Math.max(l,r);
        max=Math.max(max_lr,maxLeftBorderSum+maxRightBorderSum);
        return max;


法4:动态规划

令状态dp[i]表示以A[i]作为末尾的连续序列的最大值
当dp[i-1]>0,dp[i]=dp[i-1]+A[i]
否则,dp[i]=A[i]
所以,dp[i]=max(dp[i-1]+a[i],a[i]);

O(n)
//动态规划
    public static int maxSubSum4(int a[]){
        int maxSum=0,thisSum=0;
        for (int i=0;i<a.length;i++){
            thisSum+=a[i];
            if (thisSum>maxSum)
                maxSum=thisSum;
            else if (thisSum<0)
                thisSum=0;
        }
        return maxSum;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值