题目描述
Java
class Solution {
public int reversePairs(int[] nums) {
int len = nums.length;
if(len < 2) return 0; // 当数组中不足2个元素时,数对都不存在,直接返回 0
// 由于是一边归并排序一边计算逆序对个数的,我们的算法是会修改原始数组的,如果不允许修改,则需要将原始数组做一个拷贝
int[] copy = new int[len];
for(int i=0; i<len; i++) {
copy[i] = nums[i];
}
/*
定义一个全局的辅助数组用于归并两个有序数组,原因如下:
1.相比于每一次调用合并函数都创建一个新的辅助数组来说,更节省内存开销和资源消耗
2.如果是每次都新建一个数组进行归并,由于我们只是对数组的子区间进行拷贝,需要处理数组下标的偏移
*/
int[] temp = new int [len];
return recur(copy, 0, len-1, temp); // 递归实现归并排序
}
/*
对nums[left..right] 计算逆序对个数并且排序,注意区间范围是左闭右闭的
*/
private int recur(int[] nums, int left, int right, int[] temp) {
if(left == right) return 0; // 递归终止条件:区间只剩下一个元素时,一定不存在逆序对
// 计算当前子区间的中间位置
int mid = left + (right - left)/2; // 若写成(left+right)/2在left和right都非常大时可能会发生整型溢出
// 分别对当前子区间的前半部分和后半部分进行内部的逆序对计算
int lefPairs = recur(nums, left, mid, temp);
int rightPairs = recur(nums, mid+1, right, temp);
// 计算跨越前后两部分之间的逆序对
if(nums[mid] <= nums[mid+1]) return lefPairs + rightPairs; // 如果数组已经有序了,不需要归并了
int crossPairs = mergeAndCount(nums, left, mid, right, temp);
// 累加这三部分即为整个区间的逆序对个数
return lefPairs + rightPairs + crossPairs;
}
/*
合并前提:nums[left...mid] 有序,且nums[mid+1...right] 有序
*/
private int mergeAndCount(int[] nums, int left, int mid, int right, int[] temp) {
// 将 left到 right之间的元素拷贝到 temp数组中
for(int i=left; i<=right; i++) { // 注意区间范围是左闭右闭,因此是<=right
temp[i] = nums[i];
}
// 定义两个指针,初始化分别指向前后两部分的首个元素
int i = left, j = mid+1;
int count = 0;
for(int k=left; k<=right; k++) {
if(i == mid+1){ // 当前半部分已经没有剩下元素时
nums[k] = temp[j];
j++;
}
else if(j == right+1){ // 当后半部分已经没有剩下元素时
nums[k] = temp[i];
i++;
}
else if(temp[i] <= temp[j]) { // ps:如果写成 < 则归并排序不是稳定的排序了
nums[k] = temp[i];
i++;
}
else {
nums[k] = temp[j];
j++;
// 只有在归并后半部分的元素时,才需要计算逆序对个数,等于第一个数组还没有被归并回去的元素个数
count += (mid-i+1);
}
}
return count;
}
}
参考
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/shu-zu-zhong-de-ni-xu-dui-by-leetcode-solution/
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/jian-dan-yi-dong-gui-bing-pai-xu-python-by-azl3979/
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/bao-li-jie-fa-fen-zhi-si-xiang-shu-zhuang-shu-zu-b/