我无法在合并排序中使用java获得反转次数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我无法在合并排序中使用java获得反转次数相关的知识,希望对你有一定的参考价值。

我正在设计A[0..n − 1]是一个n个实数的数组。

如果这些数字是乱序的,即一对(A [i],A [j])被认为是反转,即,i <j但是A [i]> A [j]。 O(n log n)算法用于计算反转次数。

我正在尝试获取反转的数量,但我不知道我的代码有什么问题,我认为sort方法存在问题。

    class Q2
    { 
// Merges two subarrays of arr[]. 
// First subarray is arr[l..m] 
// Second subarray is arr[m+1..r] 
         static int merge(int arr[], int l, int m, int r) 
    { 
    // Find sizes of two subarrays to be merged 
    int n1 = m - l + 1; 
    int n2 = r - m; 
    int counter =0;

    /* Create temp arrays */
    int L[] = new int [n1]; 
    int R[] = new int [n2]; 

    /*Copy data to temp arrays*/
    for (int i=0; i<n1; ++i) 
        L[i] = arr[l + i]; 
    for (int j=0; j<n2; ++j) 
        R[j] = arr[m + 1+ j]; 


    /* Merge the temp arrays */

    // Initial indexes of first and second subarrays 
    int i = 0, j = 0; 

    // Initial index of merged subarry array 
    int k = l; 
    while (i < n1 && j < n2) 
    { 
        if (L[i] <= R[j]) 
        { 
            arr[k] = L[i]; 

            i++; 
        } 
        else
        { 
            arr[k] = R[j]; 
            j++; 
            counter = counter + (m - i); 
        } 
        k++; 

    } 

    /* Copy remaining elements of L[] if any */
    while (i < n1) 
    { 
        arr[k] = L[i]; 
        i++; 
        k++; 
    } 

    /* Copy remaining elements of R[] if any */
    while (j < n2) 
    { 
        arr[k] = R[j]; 
        j++; 
        k++; 
    } 
    return counter ;
    } 

// Main function that sorts arr[l..r] using 
// merge() 
    static int sort(int arr[], int l, int r) 
   { 
    int counter=0;
    if (l < r) 
    { 
        // Find the middle point 
        int m = (l+r)/2; 

        // count first and second halves
      counter=sort(arr, l, m); 
       counter+=sort(arr , m+1, r); 

        // count two halves
       counter+= merge(arr, l, m, r); 
    } 
    return counter;
    } 



// Driver method 
     public static void main(String args[]) 
    { 
    int arr[] = {2, 4, 1, 3,5}; 





    System.out.println("Number of inversions are " + sort(arr, 0,arr.length-1 ) ); 

      } 
      }
答案

你的方法有一个根本的缺陷。该

counter = counter + (m - i)

假设m之前的所有元素都小于R中的值,这是不正确的。请记住,m之前的数组的大部分可能已经被排序。

counter = counter + (m - l - i)

可能更正确,但在这种情况下你可能仍然计算两倍。请注意,当它们不在原始数组中的原始位置时,请对它们进行计数。

另一答案

你必须更换

 counter = counter + (m - i)

 counter = counter + (n1 - i)

示意图:假设左数组L的数字为1,6,8,9,右数组为数字4,5,7。下面显示了单个递归步骤的循环迭代:

enter image description here

通常,您可以通过以不同顺序执行反转来对数组进行排序。但是,排序所需的最小反转次数是明确的,因此与该顺序无关。由于该算法使用这些替代序列中的一个,因此它提供了明确的最小倒数。这意味着特别是没有反转计数两次或省略。

该算法为您的数组{2,4,1,3,5}提供了最少3个反转次数:(4,1),(4,3)和(2,1)。

以上是关于我无法在合并排序中使用java获得反转次数的主要内容,如果未能解决你的问题,请参考以下文章

使用归并排序计算反转次数[关闭]

如何使用归并排序计算大量输入的反转次数

使用 C++ 反转句子中的每个单词需要对我的代码片段进行代码优化

无法获得排序后的数组

计算数组中的反转

ArrayList的Java递归合并排序