Java 理解使用合并排序处理fencepost的问题

Java 理解使用合并排序处理fencepost的问题,java,arrays,mergesort,fencepost,Java,Arrays,Mergesort,Fencepost,Fencepost(又名“一个错误关闭”(OBOE),也称为“一个错误关闭”(OBOB) 给定一个数组,我通常会通过索引0迭代到array.length()(半开区间) 我注意到,某些版本的合并排序要求中值为(start+end)/2。当计算合并过程中的元素数时,我们有时会将(end-start)用作元素数或(end-mid+1)。我无法直观地理解这一点?不知何故,我很难理解这一点,每次看到任何新的实现时,我都会感觉像是在抢劫 有人能提供一种直观的方法来理解我如何应用/识别围栏柱问题吗?多维阵列

Fencepost(又名“一个错误关闭”(OBOE),也称为“一个错误关闭”(OBOB)

给定一个数组,我通常会通过索引0迭代到array.length()(半开区间)

我注意到,某些版本的合并排序要求中值为(start+end)/2。当计算合并过程中的元素数时,我们有时会将(end-start)用作元素数或(end-mid+1)。我无法直观地理解这一点?不知何故,我很难理解这一点,每次看到任何新的实现时,我都会感觉像是在抢劫

有人能提供一种直观的方法来理解我如何应用/识别围栏柱问题吗?多维阵列也是这样吗

public static BigInteger mergeSort(int[] integerArray, int start, int end) {
    if (start >= end) { // less than equal to is important for cases when start = end = 0
        return BigInteger.valueOf(0);
    }
    int middle = (start + end) / 2;
    BigInteger numInv1 = mergeSort(integerArray, start, middle);
    BigInteger numInv2 = mergeSort(integerArray, middle + 1, end);
    BigInteger numInv3 = runMerge(integerArray, start, middle, end);
    return numInv1.add(numInv2).add(numInv3);
}

private static BigInteger runMerge(int[] integerArray,
                                   int start, int middle, int end) {
    BigInteger numInv = BigInteger.valueOf(0);
    int n1 = middle - start + 1;
    /*
    number of elements in 1st array is middle - start + 1. why ?
    */

    int n2 = end - middle;       // number of elements in 2nd array
    /*
    number of elements in 2nd array is end - middle. why ?
    */

    int []p = new int[n1];
    int []q = new int[n2];
    int i, j, k;
    for (i = 0; i < n1 ; i++) {
        p[i] = integerArray[start + i];
    }
    for (j = 0; j < n2; j++) {
        q[j] = integerArray[middle + j + 1];
        //Why do we do +1 here? because we use 2nd array for mid+1 till end elements
    }
    i = 0;
    j = 0;
    k = start;
    while ( i < n1 && j < n2) {
        if (p[i] <= q[j]) {
            integerArray[k++] = p[i++];
        } else {
            integerArray[k++] = q[j++];
            numInv = numInv.add(BigInteger.valueOf(n1-i));
        }
    }
    while ( i < n1 ) {
        integerArray[k++] = p[i++];
    }
    while ( j < n2 ) {
        integerArray[k++] = q[j++];
    }
    return numInv;
}
公共静态BigInteger合并排序(int[]integerArray,int start,int end){
如果(start>=end){//小于等于对于start=end=0的情况很重要
返回BigInteger.valueOf(0);
}
中间整数=(开始+结束)/2;
biginger numInv1=mergeSort(integerArray、start、middle);
biginger numInv2=mergeSort(integerArray,中间+1,结束);
biginger numInv3=runMerge(integerArray、start、middle、end);
返回numInv1.add(numInv2.add)(numInv3);
}
私有静态BigInteger运行合并(int[]integerArray,
整数开始、整数中间、整数结束){
BigInteger numInv=BigInteger.valueOf(0);
int n1=中间启动+1;
/*
第一个数组中的元素数是中间开始+1。为什么?
*/
int n2=end-middle;//第二个数组中的元素数
/*
第二个数组中的元素数是末端-中间。为什么?
*/
int[]p=新的int[n1];
int[]q=新的int[n2];
int i,j,k;
对于(i=0;i
它们不是元素数,而是将初始数组拆分为更小数组所需的元素边缘索引。假设您有一个要排序的数组:

int[] myIntArray = {7,4,3,5,1,12,12,11,0,2};
它包含10个元素,但是索引从0到9。因此,在您的方法中
mergeSort(int[]integerArray,int start,int end);
它应该是
myIntArray,0,9
,而不是
myIntArray,1,10
myIntArray,1,9

因此,假设我们传递像
myIntArray,0,9
这样的参数,让我们看看当我们有两个排序子数组时,
mergeSort()
的最后一个(折叠方向)调用:

在计算了middle=(0+9)/2=4之后,我们在心里将初始数组分成两个数组,如下所示:

mergeSort(integerArray,start,middle);
其中start=0,middle=4(包括索引从0到4的项-均包括:1,3,4,5,7)

mergeSort(integerArray,middle+1,end);
其中start=middle+1=4+1=5,end=9(包括索引从5到9的数字-均包括:0,2,11,12,12)

这里

通过添加+1,我们得到了第5个元素。请记住,在当前调用变量的堆栈中,middle等于4,该值(4)被传递到
runMerge()
。value
middle+1
转到了先前完成的
mergeSort()调用之一

整个过程一直在进行,直到我们得到大小为1的数组,这些数组可以被认为是排序的,然后我们开始合并-当然,你已经知道了。正如你所看到的,这些变量-开始、中间、结束-是元素的位置(索引),而不是元素的数量

如果您将参数视为项的位置,如
mergeSort(myIntArray,0,9);
而不是项的数量,那么您发布的代码可以正常工作。在开始时,它应该是
array.length()-1
希望有帮助:)

第一个数组中的元素数是中间开始+1。为什么? 第二个数组中的元素数是末端-中间。为什么

它们不是元素数,而是将初始数组拆分为更小数组所需的元素边缘索引。假设您有一个要排序的数组:

int[] myIntArray = {7,4,3,5,1,12,12,11,0,2};
它包含10个元素,但是索引从0到9。因此,在您的方法中
mergeSort(int[]integerArray,int start,int end);
它应该是
myIntArray,0,9
,而不是
myIntArray,1,10
myIntArray,1,9

因此,假设我们传递像
myIntArray,0,9
这样的参数,让我们看看当我们有两个排序子数组时,
mergeSort()
的最后一个(折叠方向)调用:

在计算了middle=(0+9)/2=4之后,我们在心里将初始数组分成两个数组,如下所示:

mergeSort(integerArray,start,middle);
其中start=0,middle=4(包括索引从0到4的项-均包括:1,3,4,5,7)

mergeSort(integerArray,middle+1,end);
其中start=middle+1=4+1=5,end=9(包括索引从5到9的数字-均包括:0,2,11,12,12)

这里

通过添加+1,我们得到了第5个元素。请记住,在当前调用变量的堆栈中,middle等于4,该值(4)被传递到
runMerge()
。value
middle+1
转到了先前完成的
mergeSort()调用之一

整个过程一直在进行,直到我们得到大小为1的数组,这些数组可以被认为是排序的,然后我们开始合并-当然,你已经知道了。正如你所看到的,这些变量-s