剑指Offer:数组中的逆序对

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
示例:输入 1,2,3,4,5,6,7,0 输出 7

解析

使用快速排序,先排序2个子数组,分别记录它们排序过程中出现的逆序对。
然后合并2个子数组,p1、p2分别指向2个子数组,如果arr[p1]<arr[p2],则copy[i++]=arr[p1++],此时没有逆序对;
如果arr[p1]>=arr[p2],则copy[i++]=arr[p2++],此时逆序对的个数为mid-p1+1(p1数组从小到大排列,arr[p1]>arr[p2],则p1后面的数都大于arr[p2],即有mid-p1+1个数)

public class Solution {
    public int InversePairs(int [] array) {
        if (array == null || array.length < 2)
            return 0;
        int[] copy=new int[array.length];
        int count= mergeSort(array, copy,0, array.length - 1);
        return count;
    }
 
    public static int mergeSort(int[] arr,int[] copy, int L, int R) {
        if (L == R)
            return 0;
        int mid = L + ((R - L) >> 1);
        int left=mergeSort(arr, copy,L, mid);
        int right=mergeSort(arr,copy, mid + 1, R);
        return (left+right+mergeCount(arr, copy,L, mid, R))%1000000007;
    }
 
    public static int mergeCount(int[] arr,int[] copy, int l, int mid, int r) {
        int count = 0;
        int p1=l;
        int p2=mid+1;
        int i=0;
        //int copy[]=new int[r-l+1];
        while(p1<=mid && p2<=r){
            if(arr[p1]<arr[p2]){
                copy[i++]=arr[p1++];
            }else{
                copy[i++]=arr[p2++];
                count = (count+mid-p1+1)%1000000007;
            }
        }
        while(p1<=mid){
            copy[i++]=arr[p1++];
        }
        while(p2<=r){
            copy[i++]=arr[p2++];
        }
        for(i=0;i<r-l+1;i++){
            arr[l+i]=copy[i];
        }
        return count%1000000007;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43165002/article/details/89515219