金九银十之数组中逆序对问题

169 阅读1分钟

文字题解

利用归并排序实现
在归并排序执行过程中,默认长度为1的数组是有序的 再归并合并数组的过程中,合并前,左边是有序的,右边也是有序的 统计数量,如果左边的比右边的大,那么此时左边跟右边都是有序的 则左边剩余的数+1就是这次逆序对的数量 主要难点在于要想到逆序对的数量是怎么计算出来的

代码实现

static int temp = 0;

public static int reversePair(int[] arr) {
  if (arr == null || arr.length < 2) {
    return 0;
  }
  mergeSort(arr, 0, arr.length - 1);
  return temp;

}

public static void mergeSort(int[] arr, int L, int R) {
  if (L == R) {
    return;
  }
  int mid = L + ((R - L) >> 1);
  mergeSort(arr, L, mid);
  mergeSort(arr, mid + 1, R);
  merge(arr, L, mid, R);
}

private static void merge(int[] arr, int L, int mid, int R) {
  int[] help = new int[R - L + 1];
  int i = 0;
  int p1 = L;
  int p2 = mid + 1;
  while (p1 <= mid && p2 <= R) {
    if (arr[p1] > arr[p2]) {
      System.out.printf("[%d,%d] \n", arr[p1], arr[p2]);
      //统计数量,如果左边的比右边的大,那么此时左边跟右边都是有序的
      //则左边剩余的数+1就是这次逆序对的数量
      temp += (mid - p1 + 1);
      System.out.println(temp);
    }
    help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];

  }
 
//把左边剩余的数移入数组
  while (p1 <= mid) {
    help[i++] = arr[p1++];
  }
  //把右边剩余的数移入数组
  while (p2 <= R) {
    help[i++] = arr[p2++];
  }
  //改变原数组中的值,将该区间整体变成有序
  for (int j = 0; j < help.length; j++) {
    arr[L + j] = help[j];
  }
}