剑指 Offer 51. 数组中的逆序对
思路:归并排序
归并排序就是把一个包含 n 个数的数组,折半拆分为两个子数组,然后再将这两个子数组再分,一直分下去,直到分为n个长度为1的元素。然后两两按大小归并。如此反复,直到最后形成包含 n 个数的一个有序数组。
以示例1为例:归并排序的“分”过程
整体“分”过程如下图所示:
接下来执行在合并过程当中统计逆序对的数目(初始化逆序对的数目为0):
class Solution {
public int reversePairs(int[] nums) {
return mergeSort(nums, 0, nums.length - 1);
}
private int mergeSort (int[] arr, int l, int r) {
int count = 0;
if (l < r) {
int m = (l + r) / 2;
count += mergeSort(arr, l, m);
count += mergeSort(arr, m + 1, r);
count += merge(arr, l, m, r);
}
return count;
}
private int merge(int[] arr, int l, int m, int r) {
int[] left = Arrays.copyOfRange(arr, l , m + 1);
int[] right = Arrays.copyOfRange(arr, m + 1, r + 1);
int i = 0, j = 0, k = l, swaps = 0;
while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
arr[k++] = left[i++];
} else {
arr[k++] = right[j++];
swaps += (m + 1) - (l + i);
}
}
while (i < left.length) {
arr[k++] = left[i++];
}
while (j < right.length) {
arr[k++] = right[j++];
}
return swaps;
}
}