【发布时间】:2014-10-31 09:24:29
【问题描述】:
以下代码通过归并排序计算数组 nums(i,j 对,使得 j>i && nums[i] > nums[j])中的反转。
是否可以使用相同的方法来计算像j>i && nums[i] > 2*nums[j] 这样的特殊反转的数量?
我应该如何修改这段代码?
public static void main (String args[])
{
int[] nums = {9, 16, 1, 2, 3, 4, 5, 6};
System.out.println("Strong Inversions: " + countInv(nums));
}
public static int countInv(int nums[])
{
int mid = nums.length/2;
int countL, countR, countMerge;
if(nums.length <= 1)
{
return 0;
}
int left[] = new int[mid];
int right[] = new int[nums.length - mid];
for(int i = 0; i < mid; i++)
{
left[i] = nums[i];
}
for(int i = 0; i < nums.length - mid; i++)
{
right[i] = nums[mid+i];
}
countL = countInv (left);
countR = countInv (right);
int mergedResult[] = new int[nums.length];
countMerge = mergeCount (left, right, mergedResult);
for(int i = 0; i < nums.length; i++)
{
nums[i] = mergedResult[i];
}
return (countL + countR + countMerge);
}
public static int mergeCount (int left[], int right[], int merged[])
{
int a = 0, b = 0, counter = 0, index=0;
while ( ( a < left.length) && (b < right.length) )
{
if(left[a] <= right[b])
{
merged [index] = left[a++];
}
else
{
merged [index] = right[b++];
counter += left.length - a;
}
index++;
}
if(a == left.length)
{
for (int i = b; i < right.length; i++)
{
merged [index++] = right[i];
}
}
else
{
for (int i = a; i < left.length; i++)
{
merged [index++] = left[i];
}
}
return counter;
}
我试过了
while ((a < left.length) && (b < right.length)) {
if (left[a] <= right[b]) {
merged[index] = left[a++];
} else {
if (left[a] > 2 * right[b]) {
counter += left.length - a;
}
merged[index] = right[b++];
}
index++;
}
但是while循环中有一个错误,当left[a]<2*right[b]但left[a+n] maybe>2*right[b]时,例如左数组是{9,16}而右数组是{5,6},9但是16>2*5。我的代码只是跳过这样的情况,结果数小于应有的值
【问题讨论】:
-
顺便说一句,不要复制数组。您的所有工作都可以在
nums中完成。我敢打赌,如果您避免在每次递归调用时创建和处理数组,您将获得大量时间。实际上,在进行递归调用之前进行合并或多或少等效(此外,您的函数将是尾递归的)。 -
哦,如果你还想继续复制数组,你可以使用
System.arraycopy(见documentation)。例如,左初始化:System.arraycopy(nums, 0, left, 0, mid)
标签: java algorithm sorting mergesort