在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
:::info
1、规律:分而治之
:::
:::danger
2、分析:在归并排序的过程中,左右两个部分都是有序的,在合并两个部分的时候:
① 当左边出现比右边数字大的时候,由于左边部分是有序的,所以对于当前右边部分指针指向的数字来说,它作为逆序对的第二个数字的时候,左边部分指针指向的数字到左边部分最后一个数字都可以作为逆序对的第一个数字,所以,逆序对个数增加的数量为左边部分指针指向的位置开始,左边部分的剩余数字的个数;否则是0;
② 正常合并两个有序数组,需要注意的是当左边指针指向的数和右边指针指向的数相等的时候,先存左边部分的数字。
:::
:::success
3、步骤:归并排序的扩展
:::
:::info
4、代码:
:::
class Solution {public int reversePairs(int[] nums) {if(nums.length < 2){return 0;}return process(nums, 0, nums.length-1);}private int process(int[] nums, int left, int right){if(left == right){return 0;}int mid = left + (right-left) / 2;return process(nums, left, mid) + process(nums, mid+1, right) + merge(nums, left, mid, right);}private int merge(int[] nums, int left, int mid, int right){int[] help = new int[right-left+1];int p1 = left;int p2 = mid+1;int i = 0;int num = 0;while(p1<=mid && p2<=right){num += nums[p1] > nums[p2] ? mid-p1+1 : 0;help[i++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];}while(p1 <= mid){help[i++] = nums[p1++];}while(p2 <= right){help[i++] = nums[p2++];}for(i=0; i<help.length; i++){nums[left+i] = help[i];}return num;}}
