算法(一):最大子序列和問題的多種求解(打印子序列)

原題:給定整數(可以爲負數),A1,A2,A3,….,AN,求子序列最大的值
分析:假定-3,16,-2,12,-4,-1的序列,最大子序列爲16,-2,12=26

第一種算法

public static int maxSubSumOne() {
        int[] a= {-3,16,-2,12,-4,-1};//-3/-3,-16/-3,-16,-2/...
        int maxSum=0,indexFirst=0,indexLast=0;
        for(int i=0;i<a.length;i++) {//-3爲序列開始到最後-1
            for(int j=i;j<a.length;j++) {//i開始到最後-1
                int thisMax=0;
                for(int k=i;k<=j;k++) {
                    thisMax+=a[k];//子序列的和-3/13/11/...
                }
                if(maxSum<=thisMax) {
                    maxSum=thisMax;
                    indexFirst=i;indexLast=j;//記錄最大子序的下標
                }
            }
        }
        //打印最大子序列
        for(;indexFirst<=indexLast;indexFirst++) {
            System.out.print(a[indexFirst]+" ");
        }
        return maxSum;
    }

分析:三層嵌套,運行時間爲O(N^3)

第二種算法

public static int maxSubSumOne() {
        int[] a= {-3,16,-2,12,-4,-1;//-3/-3,-16/-3,-16,-2/...
        int maxSum=0,indexFirst=0,indexLast=0;
        for(int i=0;i<a.length;i++) {//-3爲序列開始到最後-1
            int thisMax=0;
            for(int j=i;j<a.length;j++) {//i開始到最後-1
                thisMax+=a[j];//子序列的和-3/13/11/...
                if(maxSum<=thisMax) {
                    maxSum=thisMax;
                    indexFirst=i;indexLast=j;//記錄最大子序的下標
                }
            }
        }
        //打印最大子序列
        for(;indexFirst<=indexLast;indexFirst++) {
            System.out.print(a[indexFirst]+" ");
        }
        return maxSum;
    }

分析:二層嵌套,運行時間爲O(N^2)

第三種算法

public static int maxSumThree(int[] a,int left,int right) {
        if(left==right) {//遞歸基礎:最後只有一個元素
            return a[left];//最大子序
        }
        int center =(left+right)/2;
        int maxLeftSum = maxSumThree(a,left,center);
        int maxRightSum= maxSumThree(a,center+1,right);
        int maxLeftBorderSum =0,leftBorderSum=0;
        //左側子序包含最後一個元素的最大子序列和
        for(int i=center;i>=left;i--) {//center
            leftBorderSum +=a[i];
            if(leftBorderSum>maxLeftBorderSum) {
                maxLeftBorderSum=leftBorderSum;
            }
        }
        //右側子序右半部分子序列中包含第一個元素的最大子序列和
        int maxRightBorderSum =0,rightBorderSum=0;
        for(int i=center+1;i>=left;i--) {//center+1
            rightBorderSum +=a[i];
            if(rightBorderSum>maxRightBorderSum) {
                maxRightBorderSum=rightBorderSum;
            }
        }
        //返回max3
        int maxSum=maxLeftBorderSum+maxRightBorderSum; 
        if(maxSum<maxRightSum) {maxSum=maxRightSum;}
        if(maxSum<maxLeftSum){maxSum=maxLeftSum;}
        return maxSum;
    }

public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] a= {-3,16,-2,12,-4,-1};//-3,16,-2(center)12,-4,-1
        System.out.print(maxSumThree(a,0,a.length-1));
    }

分析:使用分治策略結合遞歸思想,時間複雜度爲O(NlogN)。

第四種算法

public static int maxSumFour(int[] a) {
        int maxSum=0,thisSum=0;
        int index=0,indexFirst=0,indexLast=0;
        for(int j=0;j<a.length;j++) {
            thisSum +=a[j];
            if(thisSum>maxSum) {
                maxSum = thisSum;
                if(index==1) {//記錄打印子序列的下標
                    indexFirst=j;//開始下標
                }else {
                    indexLast=j;//結束下標
                }
            }else if(thisSum<0) {//關鍵點:累加爲負,即重新累加
                thisSum=0;
            }
        }
        //打印最大子序列
        for(;indexFirst<=indexLast;indexFirst++) {
            System.out.print(a[indexFirst]+" ");
        }
        return maxSum;
    }

分析:算法也是解決問題,如此輕巧的解決,perfect。時間複雜度爲O(N)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章