题目
代码
主体就是一个归并排序,在归并排序内部计数。
class Solution {
public int reversePairs(int[] nums) {
if(nums.length<2){
return 0;
}
// 题上没说是否可以改变原数组就不要用原来的
int[] copy=new int[nums.length];
for(int i=0;i<nums.length;i++){
copy[i]=nums[i];
}
int[] temp=new int[nums.length];
return reversePairs(copy,0,nums.length-1, temp);
}
// 其实这就是归并排序
// 全局使用一个temp,既可以防止多次创建的开销。也直接定位下标
public int reversePairs(int[] nums,int left,int right,int[] temp){
if(left==right){
return 0;
}
int mid=left+(right-left)/2;
int lcount=reversePairs(nums,left,mid,temp);
int rcount=reversePairs(nums,mid+1,right,temp);
// 归并排序的优化,如果左右子序列都有序了,那么这一轮直接返回就好
if(nums[mid]<=nums[mid+1]){
return lcount+rcount;
}
int tcount=mergeAndCount(nums,left,mid,right,temp);
return lcount+rcount+tcount;
}
public int mergeAndCount(int[] nums,int left,int mid,int right,int[] temp){
for(int i=left;i<=right;i++){
temp[i]=nums[i];
}
int count=0;
int l=left;
int r=mid+1;
for(int i=left;i<=right;i++){
// 前两个判断必须放在前面,防止越界。
if(r==right+1){
nums[i]=temp[l];
l++;
}else if(l==mid+1){
nums[i]=temp[r];
r++;
// 这是归并排序保证有序性的关键
}else if(temp[l]<=temp[r]){
nums[i]=temp[l];
l++;
}else if(temp[l]>temp[r]){
nums[i]=temp[r];
count+=mid+1-l;
r++;
}
}
return count;
}
}