Java 分治最大连续子阵(MCS)问题

Java 分治最大连续子阵(MCS)问题,java,algorithm,divide-and-conquer,sub-array,Java,Algorithm,Divide And Conquer,Sub Array,我想为给定的整数输入数组找到一个非空、连续的子数组,它可以有重复的值。我尝试了分而治之的方法来查找数组的最大连续子数组,它会返回与预期不同的结果。请在下面查找代码 private static int maxSumRec(int[] a, int low, int high) { int leftSum = 0, rightSum = 0; int sum = 0; if (low == high) { // Base case return a[lo

我想为给定的整数输入数组找到一个非空、连续的子数组,它可以有重复的值。我尝试了分而治之的方法来查找数组的最大连续子数组,它会返回与预期不同的结果。请在下面查找代码

private static int maxSumRec(int[] a, int low, int high) {
    int leftSum = 0, rightSum = 0;
    int sum = 0; 

    if (low == high) { // Base case
        return a[low]; 
    }

    int mid = (low + high) >> 1; // (low + high) / 2
    int maxLeftSum = maxSumRec(a, low, mid);
    int maxRightSum = maxSumRec(a, mid + 1, high);

    //max-crossing-subarray
    for (int i = mid; i >= low; i--) {
        sum += a[i];
        if (sum > leftSum) {
            leftSum = sum;
        }
    }
    sum = 0;
    for (int i = mid + 1; i <= high; i++) {
        sum += a[i];
        if (sum > rightSum) {
            rightSum = sum;
        }
    }
    return max3(maxLeftSum, maxRightSum, (leftSum + rightSum));
}

private static int max3(int a, int b, int c) {
    return a > b ? (a > c ? a : c) : (b > c ? b : c);
}

public static void main(String[] args) {


    //INPUT
    int a[] = {
        -5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
        78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
        78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
        5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
    };

    int maxSum = maxSumRec(a, 0, a.length - 1);
    System.out.println("Max sum is " + maxSum);
}
private static int-maxSumRec(int[]a,int-low,int-high){
int leftSum=0,rightSum=0;
整数和=0;
如果(低==高){//基本情况
返回一个[低];
}
int mid=(低+高)>>1;//(低+高)/2
int maxLeftSum=maxSumRec(a、低、中);
int maxRightSum=maxSumRec(a,中+1,高);
//最大交叉子阵
对于(int i=mid;i>=low;i--){
总和+=a[i];
如果(总和>左总和){
左和=和;
}
}
总和=0;
对于(整数i=mid+1;i右和){
rightSum=总和;
}
}
返回max3(maxLeftSum,maxRightSum,(leftSum+rightSum));
}
私有静态intmax3(inta,intb,intc){
返回a>b?(a>c?a:c):(b>c?b:c);
}
公共静态void main(字符串[]args){
//输入
INTA[]={
-5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
};
int maxSum=maxSumRec(a,0,a.length-1);
System.out.println(“最大和为”+maxSum);
}
此代码将结果返回为2000005400。MCS的非递归版本返回一个不同的结果,即2000010721及其在{1-94}中找到的结果。 我想不出原因。如果代码中有错误,请告诉我

从1到95的总和(即:4000010711)实际上大于从1到94的总和

您的
整数
太长

您需要使用
long
来获得正确的结果

注意:

public class Sample5 {
        private static long maxSumRec(int[] a, int low, int high) {
            long  leftSum = 0, rightSum = 0;
            long  sum = 0; 

            if (low == high) { // Base case
                return a[low]; 
            }

            int mid = (low + high)/2; // (low + high) / 2
            long maxLeftSum = maxSumRec(a, low, mid);
            long maxRightSum = maxSumRec(a, mid + 1, high);

            //max-crossing-subarray
            for (int i = mid; i >= low; i--) {
                sum += a[i];
                if (sum > leftSum) {
                    leftSum = sum;
                }
            }
            sum = 0;
            for (int i = mid + 1; i <= high; i++) {
                sum += a[i];
                if (sum > rightSum) {
                    rightSum = sum;
                }
            }
            System.out.println("final left sum "+leftSum);
            System.out.println("final right sum "+rightSum);
            System.out.println("leftSum+rightSUM:"+(leftSum + rightSum));
            return max3(maxLeftSum, maxRightSum, (leftSum + rightSum));
        }

        private static long max3(long a, long b, long c) {
            return a > b ? (a > c ? a : c) : (b > c ? b : c);
        }

        private static int sum(int[] a,int i,int j){
            int r=0;
            for(int k=i;k<=j;k++){
                r+=a[k];
            }
            return r;
        }
        public static void main(String[] args) {


            //INPUT
            int a[] = {
                -5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
                78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
                78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
                5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
            };

            long maxSum = maxSumRec(a, 0, a.length-1);
            System.out.println("Max sum is " + maxSum);

            //WITH INTS
            System.out.println("with ints, the sum 1 to 94 is " + sum(a,1,94));
            System.out.println("with ints, the sum 1 to 95 is " + sum(a,1,95));
        }


}
final left sum 2000005311
final right sum 2000005400
leftSum+rightSUM:4000010711
Max sum is 4000010711
with ints, the sum 1 to 94 is 2000010721
with ints, the sum 1 to 95 is -294956585
整数介于-2147483648和2147483647之间

int test=2147483647;
System.out.println(test);
System.out.println(test+1);
您将获得:

2147483647
-2147483648
试试这个:

public class Sample5 {
        private static long maxSumRec(int[] a, int low, int high) {
            long  leftSum = 0, rightSum = 0;
            long  sum = 0; 

            if (low == high) { // Base case
                return a[low]; 
            }

            int mid = (low + high)/2; // (low + high) / 2
            long maxLeftSum = maxSumRec(a, low, mid);
            long maxRightSum = maxSumRec(a, mid + 1, high);

            //max-crossing-subarray
            for (int i = mid; i >= low; i--) {
                sum += a[i];
                if (sum > leftSum) {
                    leftSum = sum;
                }
            }
            sum = 0;
            for (int i = mid + 1; i <= high; i++) {
                sum += a[i];
                if (sum > rightSum) {
                    rightSum = sum;
                }
            }
            System.out.println("final left sum "+leftSum);
            System.out.println("final right sum "+rightSum);
            System.out.println("leftSum+rightSUM:"+(leftSum + rightSum));
            return max3(maxLeftSum, maxRightSum, (leftSum + rightSum));
        }

        private static long max3(long a, long b, long c) {
            return a > b ? (a > c ? a : c) : (b > c ? b : c);
        }

        private static int sum(int[] a,int i,int j){
            int r=0;
            for(int k=i;k<=j;k++){
                r+=a[k];
            }
            return r;
        }
        public static void main(String[] args) {


            //INPUT
            int a[] = {
                -5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990,
                78, -7, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
                78, 77, 76, 75, 74, 73, 72, 80, 24, 25, 61, 69, 84, 0, -1, 145, 1902, 200, 199, 198, 197, 196, 195, 194,
                5, 71, 23, 41, 34, 1, 3, 6, 2, 91, 312, 42, 31, 67, 12, 10, 18, 56, 90, 21, 45, 47, 89, 1999999990
            };

            long maxSum = maxSumRec(a, 0, a.length-1);
            System.out.println("Max sum is " + maxSum);

            //WITH INTS
            System.out.println("with ints, the sum 1 to 94 is " + sum(a,1,94));
            System.out.println("with ints, the sum 1 to 95 is " + sum(a,1,95));
        }


}
final left sum 2000005311
final right sum 2000005400
leftSum+rightSUM:4000010711
Max sum is 4000010711
with ints, the sum 1 to 94 is 2000010721
with ints, the sum 1 to 95 is -294956585

没有足够的分数添加评论,因此创建了快速评论的答案:

Ricky的答案在大多数情况下都有效,但对于[-2,-1]这样的数组,它就不起作用了。只需添加:

leftSum=a[mid];rightSum=a[mid+1]


请详细说明您试图解决的问题(Wikipedia链接就足够了),并提供示例输入和输出。此代码如“算法简介”[CLRS]中所述。对于我在代码中介绍的输入,算法似乎会中断,除非代码中有错误。您的输入样本不是集合,[元素重复]最大子数组是什么意思?你是否在寻找i,j,使得Sigma(a[k])[对于每个i为什么不是[3,2,1,-4,5,2,-1,3]的和是11?