天天看點

數組中的逆序對題目描述解題思路代碼

題目描述

在數組中的兩個數字,如果前面一個數字大于後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。并将P對1000000007取模的結果輸出。 即輸出P%1000000007

解題思路

這道題是歸并排序的變形。我在思考的時候也想到可以用分治的思想來解決,但是在兩個子數組如何合并的問題上沒有想清楚。

這道題的解題代碼,其實可以在歸并排序的基礎上進行。其與歸并排序的差別在于,子數組合并的時候應該統計左子數組中數字比右子數組中數字大的逆序對。在合并的時候,有子數組都已排好序的前提,可以幫助我們進行逆序對的統計,具體過程看下面的示例。

數組中的逆序對題目描述解題思路代碼
數組中的逆序對題目描述解題思路代碼
數組中的逆序對題目描述解題思路代碼

代碼

public class InversePairs {
    public int InversePairs(int [] array) {
        if(array==null || array.length==0){
            return 0;
        }

        int[] copy = new int[array.length];
        for(int i=0;i<array.length;i++){
            copy[i] = array[i];
        }

        return InversePairsCore(array, copy, 0, array.length-1);
    }

    public int InversePairsCore(int[] array, int[] copy, int start, int end){
        if(start==end){
            copy[start] = array[start];
            return 0;
        }

        int length = (end-start)/2;
        int left = InversePairsCore(array, copy, start, start+length)%1000000007;
        int right = InversePairsCore(array, copy, start+length+1, end)%1000000007;

        int i = start+length;
        int j = end;
        int indexCopy = end;
        int count = 0;
        while(i>=start && j>=start + length + 1){
            if(array[i]>array[j]){
                copy[indexCopy--] = array[i--];
                count+=j-start-length;
                if(count>=1000000007)//數值過大求餘
                {
                    count%=1000000007;
                }

            }else{
                copy[indexCopy--] = array[j--];
            }
        }

        for(;i>=start;i--){
            copy[indexCopy--] = array[i];
        }
        for(;j>=start+length+1;j--){
            copy[indexCopy--] = array[j];
        }
        for(int s=start;s<=end;s++)
        {
            array[s] = copy[s];
        }
        return (left + right + count)%1000000007;
    }
}