需要帮助计算合并排序的倒置数

时间:2014-09-06 16:54:14

标签: java algorithm sorting mergesort

以下代码通过合并排序计算数组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&lt; 2 * 5 16> 2 * 5 。我的代码只是跳过这样的情况,结果数量应该小于它应该

2 个答案:

答案 0 :(得分:2)

while中的mergeCount循环有两个功能:将leftright合并到merged,并计算left的数量 - right倒置。对于特殊的反转,最简单的方法是将循环分成两部分,首先计算反转然后合并。计数反转的新触发器为left[a] > 2*right[b]

有两个循环的原因是计算特殊反转需要将left2*right合并,并且排序需要将leftright合并。可能在单个循环中使用三个不同的索引,但逻辑会更复杂。

答案 1 :(得分:0)

    while ( ( a < left.length) && (b < right.length) ) {
        if(left[a] <= right[b]) {
            merged [index] = left[a++];
        } else {
            counter += updateCounter(right[b],a,left);
            merged [index] = right[b++];
        }
        index++;
        //Rest of the while loop
    }
    //Rest of the mergeCount function
}

public static int updateCounter(int toSwitch, int index, int[] array) {
    while(index < array.length) {
        if(array[index] >= 2*toSwitch)
            break;
        index++;
    }
    return array.length-index;
}

效率不高,但应该做好。您使用index初始化a,因为低于a的元素永远不会满足条件。