4月打卡活动第24天 面试题第51题:数组中的逆序对(困难)
-
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
-
解题思路:第一想法当然是两层循环,超出时间限制也是当然的。。。
-
题解做法:
class Solution {
//记录答案
private int res = 0;
public int reversePairs(int[] nums) {
int len = nums.length;
//为了不改变原数组 新copy个数组进行计算
int[] copy = new int[len];
for(int i=0;i<len;i++){
copy[i]=nums[i];
}
//归并排序
mergeSort(copy,0,len-1);
return res;
}
/**
*nums 待排序数组
*left 当前待排序区间的左下标
*right 当前待排序区间的右下标
*/
private void mergeSort(int[] nums,int left,int right){
if(left>=right)return;
//求中点 划分左右两个区间 递归排序
int mid = (left+right)/2;
mergeSort(nums,left,mid);
mergeSort(nums,mid+1,right);
//利用一个tmp辅助数组 开始对左右两个排序后的区间合并
int l = left,r=mid+1,cur=0;
int[] tmp = new int[right-left+1];
while(l<=mid&&r<=right){
//左边区间数小于等于右边 左边先放入tmp 并更新左边指针
if(nums[l]<=nums[r]){
tmp[cur]=nums[l++];
//相对于正常归并排序多出的一个步骤 计算有多少个逆序对
res+=r-(mid+1);
}else{
tmp[cur]=nums[r++];
}
cur++;
}
//如果右边节点先到右区间边界导致上边while退出
while(l<=mid){
tmp[cur++]=nums[l++];
//相对于正常归并排序多出的一个步骤 计算有多少个逆序对
res+=r-(mid+1);
}
while(r<=right){
tmp[cur++]=nums[r++];
}
//将待排序数组 当前排好序的left~right区间重新赋值
for(int i=0;i<tmp.length;i++){
nums[left+i]=tmp[i];
}
}
}
作者:__sun
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/gui-bing-pai-xu-duo-liang-xing-dai-ma-by-__sun/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。