Fencepost (AKA An off-by-one error (OBOE),通常也称为 OBOB (off-by-one bug)。
给定一个数组,我通常会遍历索引 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;
}