题解 | #数组中的逆序对#
数组中的逆序对
https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5
import java.util.*;
public class Solution {
private int count = 0;
private final int MOD = 1000000007;
public int InversePairs(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
mergeSort(nums, 0, nums.length - 1);
return count;
}
private void mergeSort(int[] nums, int start, int end) {
if (start >= end) {
return;
}
int mid = (start + end) / 2;
mergeSort(nums, start, mid);
mergeSort(nums, mid + 1, end);
merge(nums, start, mid, end);
}
private void merge(int[] nums, int start, int mid, int end) {
int[] temp = new int[end - start + 1];
int i = start, j = mid + 1, k = 0;
while (i <= mid && j <= end) {
if (nums[i] > nums[j]) {
count = (count + (mid - i + 1)) % MOD;
temp[k++] = nums[j++];
} else {
temp[k++] = nums[i++];
}
}
while (i <= mid) {
temp[k++] = nums[i++];
}
while (j <= end) {
temp[k++] = nums[j++];
}
System.arraycopy(temp, 0, nums, start, temp.length);
}
}
使用归并排序计算逆序对数量,其实就是先拆分,在合并,在合并中,如果对于nums[i]-nums[mid]与nums[j]-nums[end],如果nums[i]>nums[j],则左子数组都是与nums[j]形成了逆序对,然后把nums[j]放入新数组中,继续比较nums[i]与nums[j+1]; 如果nums[i]<nums[j],则把nums[i]放入新数组中,继续比较nums[i+1]与nums[j],两个数组比完,也就代表这部分的逆序数求出来的,且排好序了,直到只剩一个数组,就结束了。
一开始没理解的地方:
拆分为什么不见新数组:这是因为是隐式拆分,并未形成新的数组;
拆分时为什么要有mid,直接是start到end不是更好:这是因为mid每次重复计算,保证拆分范围是变动的。
新学习的方法的功能:
System.arraycopy 的方法签名如下:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
参数说明:
src:源数组,你想要从这个数组中拷贝元素。srcPos:源数组中的起始位置,从这个位置开始拷贝。dest:目标数组,你想要拷贝元素到这个数组。destPos:目标数组中的起始位置,从这个位置开始粘贴拷贝的元素。length:要拷贝的元素数量

