劍指Offer——(35)數組中的逆序對

題目描述:

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

輸入描述:

題目保證輸入的數組中沒有的相同的數字

數據範圍:

對於%50的數據,size<=10^4
對於%75的數據,size<=10^5
對於%100的數據,size<=2*10^5

示例:

輸入
1,2,3,4,5,6,7,0
輸出
7

實現如下:

//利用歸併排序的思想,將數據分割成小數組,將小數組的逆序對求出,再依次合併小數組,求出更大範圍數組中的逆序對
//保證每一個分割的數組都是有序的,合併時繼續保證有序
//具體過程見註釋
class Solution 
{
public:
    long InversePairsCore(vector<int> &data, vector<int> &copy, long start, long end) 
    {
        if (start == end) return 0;//判斷起始下標和終止下標是否重合,重合時即爲無法再分割,結束遞歸

        long length = (end - start)//計算當前分割的數組中的元素個數
        //左右範圍繼續遞歸
        long left = InversePairsCore(copy, data, start, start + length);
        long right = InversePairsCore(copy, data, start + length + 1, end);
        long crossCount = 0;//記錄當前小數組內的逆序對個數       
        long i = start + length;//合併時,左數組的最後一個元素的下標
        long j = end;//合併時,右數組的最後一個元素的下標
        long temp = end; //記錄合併後的元素放置下標

        //開始合併,判斷左數組的i下標元素是否大於右數組的j下標元素
        while (i >= start && j >= start + length + 1)
        {   
            if (data[i] > data[j]) //若大於,將i下標元素下放到輔助數組中
            {
                copy[temp--] = data[i--];//i前移
                crossCount += j - start - length;//計算逆序對,因爲左右數組內都是有序的,所以i下標元素大於在右數組內j下標元素之前的所有元素
            }
            else//否則,將j下標元素下放到輔助數組中
                copy[temp--] = data[j--];
        }
        //將剩餘的元素下放到輔助數組內
        while (i >= start)
            copy[temp--] = data[i--];

        while (j >= start + length + 1)
            copy[temp--] = data[j--];

        return (left + right + crossCount) % 1000000007;//返回左右數組內部的逆序對個數與當前合併時數組中的逆序對個數之和,按照提述取模
    }

    int InversePairs(vector<int> &data) 
    {
        if (data.size() == 0) return 0;//當沒有數據時,返回0個
        else if (data.size() == 1) return 1;//當只有一個數據時,返回1個
        else 
        {
            vector<int> copy(data);//借用輔助數組空間,用來保存合併後的數據
            return InversePairsCore(copy, data, 0, data.size() - 1);
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章