求一个数组的逆序对总数=求一个数右边有多少个数比它小
逆序对就是一个数组中前面的值和大于后面的值的一组数。
那么把数组分成前后两部分,分别进行归并,归并到最后merge两个数组,在这个过程中排序,并且计算出有多少个数是逆序的。
这样到后来归并两个数组的时候,已经知道两个数组各自有多少逆序对了,只需要计算归并过程中产生的逆序对。因为已经是排序完的,所以找到第一个大于第二段中的值的时候,第二个值一定小于全部的第一段中的值,所以count要加上第一段中的剩下的所有数据。
注意两点1.进行移位操作的时候一定记得加上括号,因为优先级较低。
2.进行计算的时候因为数据量比较大,所以都要取余
public class Solution {
public int InversePairs(int [] array) {
if(array==null || array.length==0){
return 0;
}
int res=mergeSort(array,0,array.length-1);
return res%1000000007;
}
public int mergeSort(int[] arr,int lo,int hi){
if(lo==hi){
return 0;
}
int mid=lo+((hi-lo)>>1);
int res1=mergeSort(arr,lo,mid)%1000000007;
int res2=mergeSort(arr,mid+1,hi)%1000000007;
int res3=merge(arr,lo,mid,hi)%1000000007;
return (res1+res2+res3)%1000000007;
}
public int merge(int[] arr,int lo,int mid,int hi){
int[] res=new int[hi-lo+1];
int cur=0;
int cur1=lo;
int cur2=mid+1;
int count=0;
while(cur1<=mid && cur2<=hi){
if(arr[cur1]>arr[cur2]){
count+=mid-cur1+1;
count%=1000000007;
}
if(arr[cur1]<=arr[cur2]){
res[cur++]=arr[cur1++];
}else{
res[cur++]=arr[cur2++];
}
}
while(cur1<=mid){
res[cur++]=arr[cur1++];
}
while(cur2<=hi){
res[cur++]=arr[cur2++];
}
for(int i=0;i<res.length;i++){
arr[lo+i]=res[i];
}
return count;
}
}
求一个数组的小和=求一个数右边有多少个比它大
小和就是左边所有小于自己的和,返回一个所有数的小和之和,每次sort或者merge都产生一个小和,最终返回3个小和之和。在merge的过程中,找左边所有小于自己的数,其实就是找右边所有大于自己的数,也就是merge时右边的值直接排序并跳过,左边的值小的话就是右边此时的剩下的值都大于左边这个数,左边这个数乘右边数的数量就是左边这个数产生的小和。
public static int smallSum(int[] a){//小和问题,就是求出一个数组的每个值的(左边所有小于它的值和)和
//利用递归来解决,看成是求每个值右边有几个比它大的值
if(a==null &&a.length<=2)return 0;
return merge(a,0,a.length-1);
}
static int mergeSort(int[] a,int L,int R){
if(L==R)return 0;
int mid=L+((R-L)>>1);
int r1=mergeSort(a,L,mid);
int r2=mergeSort(a,mid+1,R);
int r3=merge(a,L,mid,R);
return r1+r2+r3;
}
static int merge(int[] a,int L,int mid ,int R){
int[] help=new int[R-L+1];
int p1=L;
int p2=mid+1;
int i=0;
int rst=0;
while(p1<=mid && p2<=R){
rst+=a[p1]<a[p2]?(a[p1]*(R-p2+1)):0; //注意这里是减p2,加一才会算上另一个边界
help[i++]=a[p1]<=a[p2]?a[p1++]:a[p2++];
}
while(p1<=mid){
help[i++]=a[p1++];
}
while(p2<=R){
help[i++]=a[p2++];
}
for(int j=0;j<help.length;j++){
a[L+j]=help[j];
}
return rst;
}