我试图编写代码来查找数字数组中的反转。我已经看到使用Merge Sort的算法正确地执行了此操作,但对逻辑有疑问。
为什么我们必须计算左右子阵列中的反转以及两者之间的反转?我的意思是显然这是正确的,但为什么我们不能计算合并步骤中的所有反转?事实证明,在进行合并的每个级别,可以直接计算反转次数,并且在生成两倍大小的子阵列之后,它的任何两个元素的相对顺序在后续合并步骤中将永远不会改变,这意味着我们永远不会计算任何最终不会反转的反转。那么,逻辑有什么问题,因为它没有给出正确的答案。
如果你愿意,我可以用例子和/或代码解释一下;故意没有包含代码,所以没有人怀疑这是作业。
编辑:到目前为止,我发现逻辑没有任何问题,而是导致错误答案的代码中的错误。
所以,这是在数组中查找反转的方法:
private void findInversions(int begin, int end, int count) {
if (end - begin < 1)
return;
int middle = (begin + end) / 2;
findInversions(begin, middle, count);
System.out.println("But here count is " + count + " and I can't find why.");
findInversions(middle + 1, end, count);
count = mergeAndCount(begin, middle, end, count);
System.out.println("count now is: " + count);
}
mergeAndCount()
方法显而易见:
private int mergeAndCount(int begin, int middle, int end, int count) {
int[] result = new int[end - begin + 1];
int aptr = begin;
int bptr = middle + 1;
for (int i = 0; i < result.length; i++) {
if (aptr <= middle && bptr <= end) {
if (numbers[aptr] < numbers[bptr]) {
result[i] = numbers[aptr];
aptr++;
}
else {
// (a[aptr], b[bptr]) is an inversion here
count++;
System.out.println("Found: (" + numbers[aptr] + "," + numbers[bptr] + "). If you print 'count' here it'll be one. See: " + count);
result[i] = numbers[bptr];
bptr++;
}
}
else if (aptr > middle) {
result[i] = numbers[bptr];
bptr++;
}
else if (bptr > end) {
result[i] = numbers[aptr];
aptr++;
}
}
for (int i = 0; i < result.length; i++) {
numbers[begin + i] = result[i];
}
return count;
}
我将计数设置为零的方法调用:findInversions(0, numbers.length - 1, 0)
。
显然问题是count
不能在不同的递归中保持其值。这是Java,因此我不需要使用&符号传递它,我甚至在mergeAndCount()
中返回它的值。那么这里有什么不对?