最大子序列和

最大子序列和

给定(可能有负的)整数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;
    }

发布了39 篇原创文章 · 获赞 31 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章