思路:使用普通的暴力解法会超时。选择使用归并算法(分治的思想)来解决这个问题。归并算法是将两个排好序的子数组中的元素进行排序。选择两个数组首部较小的一个放入新创建的数组当中。此时就能利用这个机制来实现题目要求。当后面一半数组第一个元素小于前面数组首部元素时,判断前半数组中还有多少个元素n,就是在这两个数组所有元素中,有n个数在该数前面,并且比它大。将所有n加起来,即题目中总的逆序对的数目。
思路就是后一个数组中有元素要放入数组时,看看前一半数组中还有几个没有放进去。就是有几个比它大,组成逆序对。
class Solution {
//普通方法超时,尝试使用归并算法 顺便求出题目中要求的东西。
//思路就是后一个数组中有元素要放入数组时,看看前一半数组中还有几个没有放进去。就是有几个比它大,组成逆序对。
int count=0;
public int reversePairs(int[] nums) {
if(nums==null||nums.length==0){
return 0;
}
int len=nums.length;
guiBing(nums,0,len-1);
return count;
}
public void guiBing(int[] arr,int left,int right){
int mid=(right+left)/2;
if(mid-left>0){
guiBing(arr,left,mid);
}
if(right-mid>1){
guiBing(arr,mid+1,right);
}
//并
int[] tempArr = new int[right-left+1];
int index=0;
int ll=left;
int rr=mid+1;
while(ll<=mid && rr<=right){
//比较 找出较小的一个放入新数组
if(arr[ll] > arr[rr]) {
tempArr[index++]=arr[rr];
rr++;
count=count+(mid-ll+1);
// 3 7 8 5 9
}else{
tempArr[index++]=arr[ll];
ll++;
}
}
while(ll<=mid){
tempArr[index++]=arr[ll++];
}
while(rr<=right){
tempArr[index++]=arr[rr++];
}
for(int i=left ,j=0; i<=right;i++,j++){
arr[i]=tempArr[j];
}
}
}