题目链接:LCR 170. 交易逆序对的总数
题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例:
输入: [7,5,6,4]
输出: 5
其中0 <= 数组长度 <= 50000
。
解法
显然暴力法O(n^2)
性能不够好,暴力法的缺点在于每一次比较的信息都没有被重复利用。这里可以利用归并排序法中的部分有序的性质寻找逆序数。
归并排序法利用分治,每次将数组分为两半,分别排序,再在O(n)
时间内将两个有序数组合并为一个大的有序数组。这道题目只需要在归并排序的过程中加入计数即可。
代码
Java(去掉有关count的部分即为归并排序代码):
class Solution {
private int count = 0;
public int reversePairs(int[] nums) {
mergeSort(nums, 0, nums.length - 1);
return count;
}
public void mergeSort(int[] nums, int left, int right) {
if (left == right) return;
int mid = (left + right) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, right);
}
public void merge(int[] nums, int left, int right) {
int[] tmp = new int[right - left + 1];
int mid = (left + right) / 2;
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (nums[i] > nums[j]) {
count = count + mid - i + 1;
tmp[k++] = nums[j++];
} else {
tmp[k++] = nums[i++];
}
}
while (i <= mid) {
tmp[k++] = nums[i++];
}
while (j <= right) {
tmp[k++] = nums[j++];
}
if (tmp.length >= 0) System.arraycopy(tmp, 0, nums, left, tmp.length);
}
}