【问题标题】:Finding all inversions of an array using Merger-Sort使用合并排序查找数组的所有反转
【发布时间】:2021-11-02 22:33:45
【问题描述】:

我正在尝试实现流行的算法,以使用合并排序查找数组的所有反转,但它一直输出错误的答案,它计算的反转太多 - 我相信部分或全部子数组也在迭代多次重复调用?我不能完全把我的手指放在它身上——我希望能得到一些关于为什么会发生这种情况的指示。请在下面查看我在 java 中的实现:

public class inversionsEfficient {

  public int mergeSort(int[] list, int[] temp, int left, int right) {
    int count = 0;
    int mid = 0;

    if(right > left) {
      mid = (right+left)/2;
      count += mergeSort(list, temp, left, mid);
      count += mergeSort(list, temp, mid+1, right);
      count += merge(list, temp, left, mid+1, right);
    }

    return count;
  }

  public int merge(int[] list, int[] temp, int left, int mid, int right) {
    int count = 0;
    int i = left;
    int j = mid;
    int k = left;

    while((i<=mid-1) && (j<=right)) {
      if(list[i] <= list[j]) {
        temp[k] = list[i];
        k += 1;
        i += 1;
      }
      else {
        temp[k] = list[j];
        k += 1;
        j += 1;
        count += mid-1;
      }
    }

    while(i<=mid-1) {
      temp[k] = list[i];
      k += 1;
      i += 1;
    }

    while(j<=right) {
      temp[k] = list[j];
      k += 1;
      j += 1;
    }

    for(i=left;i<=right;i++) {
      list[i] = temp[i];
    }

    return count;
  }

  public static void main(String[] args) {
    int[] myList = {5, 3, 76, 12, 89, 22, 5};
    int[] temp = new int[myList.length];

    inversionsEfficient inversions = new inversionsEfficient();
    System.out.println(inversions.mergeSort(myList, temp, 0, myList.length-1));
  }
}

该算法基于 Cormen 的算法简介中的伪代码: [1]:https://i.stack.imgur.com/ea9No.png

【问题讨论】:

    标签: java arrays recurrence inversion


    【解决方案1】:

    而不是-

    count += mid - 1;

    试试-

    count += mid - i;

    整个解决方案变成如下图:-

    public class inversionsEfficient {
    
        public int mergeSort(int[] list, int[] temp, int left, int right) {
            int count = 0;
            int mid = 0;
    
            if (right > left) {
                mid = (right + left) / 2;
                count += mergeSort(list, temp, left, mid);
                count += mergeSort(list, temp, mid + 1, right);
                count += merge(list, temp, left, mid + 1, right);
            }
    
            return count;
        }
    
        public int merge(int[] list, int[] temp, int left, int mid, int right) {
            int count = 0;
            int i = left;
            int j = mid;
            int k = left;
    
            while ((i <= mid - 1) && (j <= right)) {
                if (list[i] <= list[j]) {
                    temp[k] = list[i];
                    k += 1;
                    i += 1;
                } else {
                    temp[k] = list[j];
                    k += 1;
                    j += 1;
                    count += mid - i; // (mid - i), not (mid - 1)
                }
            }
    
            while (i <= mid - 1) {
                temp[k] = list[i];
                k += 1;
                i += 1;
            }
    
            while (j <= right) {
                temp[k] = list[j];
                k += 1;
                j += 1;
            }
    
            for (i = left; i <= right; i++) {
                list[i] = temp[i];
            }
    
            return count;
        }
    
        public static void main(String[] args) {
            int[] arr = {5, 3, 76, 12, 89, 22, 5};
            int[] temp = new int[arr.length];
    
            inversionsEfficient inversions = new inversionsEfficient();
            System.out.println(inversions.mergeSort(arr, temp, 0, arr.length - 1));
        }
    
    }
    

    上面代码对问题中提到的示例数组生成的输出是8,这是正确的,因为数组[5, 3, 76, 12, 89, 22, 5]中有8个反转-

     1. (5, 3)
     2. (76, 12)
     3. (76, 22)
     4. (76, 5)
     5. (12, 5)
     6. (89, 22)
     7. (89, 5)
     8. (22, 5)
    

    代码变更说明

    该算法将所需的反转次数计算为左子数组中的反转次数+右子数组中的反转次数+合并过程中的反转次数之和。

    如果list[i] &gt; list[j],则有(mid – i) 倒置,因为左右子数组已排序。这意味着左子数组(list[i+1], list[i+2] … list[mid]) 中的所有剩余元素也将大于list[j]

    如需更详细的解释,请查看GeeksForGeeks article on Counting Inversions

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 2017-02-08
      相关资源
      最近更新 更多