思路
暴力解法很简单但是效率很低,通不过。
通过归并排序进行统计逆序的个数。
首先归并排序包括划分和合并两个步骤。合并就是将两个已经排好序的子数组进行有序合并。有序合并的代码是一个简单题。就是从头到尾俩俩比较即可。
if(left[i]<=right[j]){
如果是左边的比右边的小,则为升序,直接放入一个临时数组即可。
}else{
此时为逆序,left[i]>right[j],则需要统计下此时的逆序对个数。因为left和right都是有序数组。所以left[大于i]肯定>right[j],所以肯定都是逆序对,所以此时产生的逆序对数为mid-i+1,mid为left数组的最右边位置。
}
代码
class Solution {
public int count = 0;
public int reversePairs(int[] nums) {
mergeSort(nums, 0, nums.length - 1);
return this.count;
}
public void merge(int[] nums, int start, int end, int mid) {
int i = start, j = mid + 1;
int[] temp = new int[end - start + 1];
int index = 0;
while (i <= mid && j <= end) {
if (nums[i] <= nums[j]) {
temp[index++] = nums[i++];
} else {
this.count += mid - i + 1;//这一步很关键,在对左右两个有序序列进行比较时,可以发现,left[i]和right[j]进行的比较,如果
//left[i]比right[j]要大,那么说明left中i后面的也比j大,所以这一步需要加上的是mid-i+1,left中这么多都是大于right[j]的
temp[index++] = nums[j++];
}
}
while (j <= end)
temp[index++] = nums[j++];
while (i <= mid)
temp[index++] = nums[i++];
for (int f = 0; f < index; f++)
nums[start + f] = temp[f];
}
public void mergeSort(int[] nums, int start, int end) {
if (start >= end) return;
int mid = (start + end) >> 1;
mergeSort(nums, start, mid);
mergeSort(nums, mid + 1, end);
merge(nums, start, end, mid);
}
}