最大总和子阵列

时间:2014-12-11 08:26:50

标签: java arrays algorithm arraylist

我试图找到具有最大总和的数组中的连续子数组。所以,对于数组

  

{5,15,-30,10,-5,40,10}

使用连续这些数字的最大总和将是55,或者(10 +( - 5)+ 40 + 10)= 55.下面的程序输出最大值55,但是,我想弄清楚的问题是如何打印产生这个55的序列。换句话说,我怎样才能打印出10,-5,40和10?

public static void main(String[] args) {
    int[] arr = {5, 15, -30, 10, -5, 40, 10};

    System.out.println(maxSubsequenceSum(arr));         
}

public static int maxSubsequenceSum(int[] X) {
    int max = X[0];
    int sum = X[0];

    for (int i = 1; i < X.length; i++) {
        sum = Math.max(X[i], sum + X[i]);
        max = Math.max(max, sum);
    }
    return max;
}

我正在考虑创建一个ArrayList来存储i的每个索引的sum值,因此ArrayList看起来像(5,20,-10,10,5,45,55)。然后我计划将ArrayList从索引0清除到列表中的第一个负数,但是,这只解决了这个特定示例的问题,但是如果我更改了原始的数字数组,这个解决方案就不会出现问题。工作

7 个答案:

答案 0 :(得分:4)

您可以用if语句替换Math.Max函数,并更新最佳子数组的开始和结束索引。 Pascal版本:

    if X[i] > sum + X[i] then begin
        sum := X[i];
        start := i;
      end
      else
        sum := sum + X[i];
      if max < sum then begin
        max := sum;
        finish := i;
      end;

答案 1 :(得分:2)

有一个o(n)解决方案,一个for循环通过数组并在当前总数低于0时重置子序列。

{5,15,-30,10,-5,40,10}

  • 5 + 15 = 20
  • 20 - 30 = -10(重置子序列)
  • 10 -5 +40 +10 = 55
  • 端。 55是最大子序列

编辑:获得后续... 每当您更改最大值时,请更新您的子序列

  • 当前左侧索引仅在u reset
  • 时更改
  • 当前权利指数每次迭代都会更改
  • new max - &gt;保存当前左右索引......

答案 2 :(得分:2)

您可以跟踪循环中当前最佳子阵列的起始和结束索引。不要使用max()计算summax,只需执行以下操作:

int sum_start = 0, sum_end = 0, start = 0, end = 0;
// In the for loop
if (X[i] > sum + X[i]) {
    sum = X[i];
    sum_start = i;
    sum_end = i;
} else {
    ++sum_end;
}
if (sum > max) {
    start = sum_start;
    end = sum_end;
    max = sum;
}

答案 3 :(得分:0)

可以通过捕获开始和结束同时识别最大子阵列来完成,如下所示:

代码

package recursion;

import java.util.Arrays;

public class MaximumSubArray {

    private static SubArray maxSubArray(int[] values, int low, int high) {
        if (low == high) {
            // base condition
            return new SubArray(low, high, values[low]);
        } else {
            int mid = (int) (low + high) / 2;
            // Check left side
            SubArray leftSubArray = maxSubArray(values, low, mid);
            // Check right side
            SubArray rightSubArray = maxSubArray(values, mid + 1, high);
            // Check from middle
            SubArray crossSubArray = maxCrossSubArray(values, low, mid, high);
            // Compare left, right and middle arrays to find maximum sub-array
            if (leftSubArray.getSum() >= rightSubArray.getSum()
                    && leftSubArray.getSum() >= crossSubArray.getSum()) {
                return leftSubArray;
            } else if (rightSubArray.getSum() >= leftSubArray.getSum()
                    && rightSubArray.getSum() >= crossSubArray.getSum()) {
                return rightSubArray;
            } else {
                return crossSubArray;
            }
        }
    }

    private static SubArray maxCrossSubArray(int[] values, int low, int mid,
            int high) {
        int sum = 0;
        int maxLeft = low;
        int maxRight = high;

        int leftSum = Integer.MIN_VALUE;
        for (int i = mid; i >= low; i--) {
            sum = sum + values[i];
            if (sum > leftSum) {
                leftSum = sum;
                maxLeft = i;
            }
        }

        sum = 0;
        int rightSum = Integer.MIN_VALUE;
        for (int j = mid + 1; j <= high; j++) {
            sum = sum + values[j];
            if (sum > rightSum) {
                rightSum = sum;
                maxRight = j;
            }
        }
        SubArray max = new SubArray(maxLeft, maxRight, (leftSum + rightSum));
        return max;
    }

    static class SubArray {

        private int start;

        private int end;

        private int sum;

        public SubArray(int start, int end, int sum) {
            super();
            this.start = start;
            this.end = end;
            this.sum = sum;
        }

        public int getStart() { return start; }

        public void setStart(int start) { this.start = start; }

        public int getEnd() { return end; }

        public void setEnd(int end) { this.end = end; }

        public int getSum() { return sum; }

        public void setSum(int sum) { this.sum = sum; }

        @Override
        public String toString() {
            return "SubArray [start=" + start + ", end=" + end + ", sum=" + sum + "]";
        }
    }

    public static final void main(String[] args) {
        int[] values = { 5, 15, -30, 10, -5, 40, 10 };
        System.out.println("Maximum sub-array for array"
            + Arrays.toString(values) + ": " + maxSubArray(values, 0, 6));
    }

}

输出

Maximum sub-array for array[5, 15, -30, 10, -5, 40, 10]: SubArray [start=3, end=6, sum=55]

可以从https://github.com/gosaliajigar/Programs/blob/master/src/recursion/MaximumSubArray.java

下载解决方案

答案 4 :(得分:0)

两个子数组是

[1, 2, 3]

和 [4, 9] 不包括负数

这里的最大子数组是 [4, 5]

所以输出是 9

这是代码

public class MaxSubArray{
static void sumM(int a[], int n){
    int s1 = Integer.MAX_VALUE;
    int k = Integer.MAX_VALUE;
    int sum = 0;
    int s2 = 0;
    for(int i=0;i<n;i++){

        if(a[i]<s1){
            if(a[i]<0){
                k = Math.min(a[i],s1);
            }
        }

        if(a[i]>k){
            sum+=a[i];
        }

        if(a[i]<k){
            if(a[i]<0){
                continue;
                
            }
            s2+=a[i];
        }

    }
        if(sum>s2){
            System.out.println(sum);
        }
        else{
            System.out.println(s2);
        }
    
     
}

    public static void main(String[] args){
        int a[] = {1,2,3,-7,4,5};

        int n = a.length;

        sumM(a,n);
    }

    
}

答案 5 :(得分:0)

 public static int kadane(int[] A) {
        
    int maxSoFar = 0;
 
        
    int maxEndingHere = 0;
 
    // traverse the given array
    for (int i: A) {
         // update the maximum sum of subarray "ending" at index `i` (by adding the
         // current element to maximum sum ending at previous index `i-1`)
         maxEndingHere = maxEndingHere + i;
 
         // if the maximum sum is negative, set it to 0 (which represents
         // an empty subarray)
         maxEndingHere = Integer.max(maxEndingHere, 0);
 
         // update the result if the current subarray sum is found to be greater
         maxSoFar = Integer.max(maxSoFar, maxEndingHere);
     }
 
     return maxSoFar;
}

答案 6 :(得分:-3)

你需要总结所有可能的子数组。要做到这一点,你可以做这个代码

public static int maxSubsequenceSum(int[] X) {
    int max = 0;
    boolean max_init = false;
    int max_from=0;
    int max_to=0; // this is not included
    for (int i = 0; i < X.length; i++) {
        for (int j = i + 1; j < X.length + 1; j++) {
            int total = 0;
            for (int k = i; k < j; k++) {
                total += X[k];
            }
            if (total > max || !max_init){
                max = total;
                max_init = true;
                max_from = i;
                max_to = j;
           }
        }
    }
    for (int i=max_from;i<max_to;i++)
       System.out.print(X[i]+",");
    System.out.println();
    return max;
}