1. 程式人生 > >在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。

在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。

 /*
       最簡單的思路:陣列的所有數兩兩比較,進行累加,空間複雜度為O(n^2)

 */

class Solution {
public:
    int InversePairs(vector<int> data) {
        int P = 0;
        if(data.size()<2)
            return P;
        for(int i=0;i<data.size()-1;i++){
            for(int j=i+1;j<data.size();j++){
                if(data[i] > data[j])
                    P++;
            }
        }
        return P%1000000007;
       
    }
};

/*
思路二:
歸併排序的改進,把資料分成前後兩個陣列(遞迴分到每個陣列僅有一個數據項),
合併陣列,合併時,出現前面的陣列值array[i]大於後面陣列值array[j]時;則前面
陣列array[i]~array[mid]都是大於array[j]的,count += mid+1 - i
參考劍指Offer,但是感覺劍指Offer歸併過程少了一步拷貝過程。
還有就是測試用例輸出結果比較大,對每次返回的count mod(1000000007)求餘
*/

class Solution {
public:
    int P = 0;
    int InversePairs(vector<int> data) {        
        if(data.size()<2)
            return P;
        vector<int> copy ;
        for(int i=0;i<data.size();i++){
            copy.push_back(data[i]);
        }
        mergeSort(data,copy,0,data.size()-1);
        return P%1000000007;
    }
    void mergeSort(vector<int> &data,vector<int> &copy,int begin,int end){
        if(begin < end){
            int mid = (begin + end)/2;
            mergeSort(data,copy,begin,mid);
            mergeSort(data,copy,mid+1,end);
            merge(data,copy,begin,mid,end);
        }
    }
    void merge(vector<int> &data,vector<int> &copy,int begin,int mid,int end){
        
        int i = begin,j = mid + 1;
        while(i<=mid && j<=end){
            if(data[i] <= data[j])
                copy.push_back(data[i++]);
            else{
                copy.push_back(data[j++]);
                P += mid - i + 1;
            }
        }
        while(i <= mid)
            copy.push_back(data[i++]);
        while(j <= end)
            copy.push_back(data[j++]);
        for(int k=begin;k<end;k++){
            data[k] = copy[k];
        }
    }
};