java 最大总和子数组

kuhbmx9i  于 2022-10-30  发布在  Java
关注(0)|答案(8)|浏览(193)

我试图在一个数组中找到一个连续的子数组,这个子数组的和最大。
{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到列表中第一个负数的内容,然而,这只解决了这个特定示例的问题,但是如果我改变了原始的数组,这个解决方案就不起作用了。

kgsdhlau

kgsdhlau1#

你可以用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;
sd2nnvve

sd2nnvve2#

你可以跟踪循环中当前最佳子数组的开始和结束索引。不用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;
}
0dxa2lsx

0dxa2lsx3#

有一个O(n)的解决方案,一个遍历数组的for循环,每当当前的总数小于0时,就重置子序列。
{5、15、-30、10、-5、40、10}

  • 五加十五=二十
  • 20 - 30 = -10(复位子序列)
  • 10 -5 +40 +10 = 55
  • end.55是最大子序列

编辑:获取子序列...每当你改变最大值时,更新你的子序列

  • 当前左索引仅在u重置时更改
  • 当前右索引在每次迭代时更改
  • 新建最大值-〉保存当前左右索引...
6rqinv9w

6rqinv9w4#

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

代码

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下载解决方案

lnvxswe2

lnvxswe25#

两个子阵列是
[一、二、三]
和[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);
    }

}
qco9c6ql

qco9c6ql6#

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;
}
bprjcwpo

bprjcwpo7#

var maxSequence = function(arr){
  // ...
  if (arr.every((ele) => ele >= 0)) {
    return arr.reduce((sum, ele) => sum + ele, 0);
  } else if (arr.every((ele) => ele < 0)) {
    return 0; 
//for me the maximum would be the biggest negative number 
//arr.reduce((max, elm) => (max > elm ? max : elm))
  } else if (arr === [0]) {
    return 0;
  } else {
    let maxSum = [];
    let currentSum = 0;
    for (let i = 0; i < arr.length; i++) {
      currentSum = Math.max(arr[i], currentSum + arr[i]);
      maxSum.push(currentSum);
    }
    return maxSum.reduce((max, elm) => (max > elm ? max : elm));
  }
}
l2osamch

l2osamch8#

你需要对所有可能的子数组求和。2要做到这一点,你可以这样做:

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;
}

相关问题