算法与数据结构

最大子序列和问题的求解

2019-06-11  本文已影响0人  小生不cai

怎么求出一个数组最大的连续累加之和呢?方法有很多,我们目前只讲一个比较不错的方法,该方法使用了分治递归的思想。

我们假设下面是我们需要计算的数组,其中A是游标,我可以知道游标将数组分成了两段,最大值有可能出现在前半段也有可能出现在后半段,还有一种情况是跨越A(中间)相加的一段。

[1,-3,5,7 A,9,-8,6,2]

跨越A相加的部分我们可以这样计算:


int maxLeftBorderSum =0;

int leftBorderSum =0;

for (int i = center;i >= left;i--){

    leftBorderSum += array[i];

    if (leftBorderSum>maxLeftBorderSum){

          maxLeftBorderSum = leftBorderSum;

    }

}

int maxRightBorderSum =0;

int rightBoederSum =0;

for (int i = center +1;i <= right;i++){

    rightBoederSum += array[i];

    if (rightBoederSum>maxRightBorderSum){

          maxRightBorderSum = rightBoederSum;

    }

}

以中间为起点向两边相加,然后将左右两边最大和相加:maxLeftBorderSum+maxRightBorderSum,即可得跨越A相加最大的。

前后端最大值可以通过递归求得:


int center = (left + right)/2;

int maxLeftSum =maxSumRec(array,left,center);

int maxRightSum =maxSumRec(array,center+1,right);

最后我们分析一下这个递归方法的基准方法:


if (left == right){

if (array[left]>0){
        return array[left];
    }else {
        return 0;
    }
}

因此完整的程序是:


public static void main(String[] args)throws Exception {

int[] array = {1,-5,4,6,-7,3,2,-5,9};

    System.out.println("结果:"+maxSumRec(array,0,array.length-1));

}

public static int maxSumRec(int[] array,int left,int right){

if (left == right){

if (array[left]>0){

return array[left];

        }else {

return 0;

        }

}

int center = (left + right)/2;

    int maxLeftSum =maxSumRec(array,left,center);

    int maxRightSum =maxSumRec(array,center+1,right);

    int maxLeftBorderSum =0;

    int leftBorderSum =0;

    for (int i = center;i >= left;i--){

leftBorderSum += array[i];

        if (leftBorderSum>maxLeftBorderSum){

maxLeftBorderSum = leftBorderSum;

        }

}

int maxRightBorderSum =0;

    int rightBoederSum =0;

    for (int i = center +1;i <= right;i++){

          rightBoederSum += array[i];

        if (rightBoederSum>maxRightBorderSum){
                maxRightBorderSum = rightBoederSum;
        }

}

return     max(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);
}

public static int max(int v1,int v2,int v3){
    if (v1>v2){
        return v1>v3?v1:v3;
    }else {
        return v2>v3?v2:v3;
    }
}

最后返回三者的最大值即可求得。

这种算法算是效率比较高的,但是根据合成效益法则可知,这个算法仍然有重复计算的部分。
下面说的这种算是则不会出现这种情况,只会对数组进行一次扫描。

public static void main(String[] args) throws Exception {
        int[] array = {1,-5,4,6,-7,3,2,-5,9};
        System.out.println("结果:"+maxSubSum(array));

    }

    public static int maxSubSum(int array[]){
        int thisSum = 0;
        int maxSum = 0;
        for (int i = 0;i<array.length;i++){
            thisSum += array[i];
            if (thisSum>maxSum){
                maxSum = thisSum;
            } else if (thisSum<0){
                thisSum = 0;
            }
        }
        return maxSum;
    }

这种算法是仅需要常量空间并以线性时间运行的联机算法。

上一篇下一篇

猜你喜欢

热点阅读