Java 理解使用合并排序处理fencepost的问题
Fencepost(又名“一个错误关闭”(OBOE),也称为“一个错误关闭”(OBOB) 给定一个数组,我通常会通过索引0迭代到array.length()(半开区间) 我注意到,某些版本的合并排序要求中值为(start+end)/2。当计算合并过程中的元素数时,我们有时会将(end-start)用作元素数或(end-mid+1)。我无法直观地理解这一点?不知何故,我很难理解这一点,每次看到任何新的实现时,我都会感觉像是在抢劫 有人能提供一种直观的方法来理解我如何应用/识别围栏柱问题吗?多维阵列也是这样吗Java 理解使用合并排序处理fencepost的问题,java,arrays,mergesort,fencepost,Java,Arrays,Mergesort,Fencepost,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()
。valuemiddle+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()
。valuemiddle+1
转到了先前完成的mergeSort()调用之一
整个过程一直在进行,直到我们得到大小为1的数组,这些数组可以被认为是排序的,然后我们开始合并-当然,你已经知道了。正如你所看到的,这些变量-s