歸並排序 之 逆序對
1. 歸並排序
要點:
歸並排序是建立在歸並操作的一種有效的算法,該算法是采用 分治法 的典型應用。
基本思想:
(1)分解:將序列每次折半劃分成兩個數組,直到劃分成每個元素一個數組
(2)合並:將劃分後的序列段兩兩合並後排序。
2.逆數對問題
在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數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
我們可以發現,其實就是要找 每個數的左邊的比他大的數一共有多少個?
(1)第一想法:兩個for循環可以解決問題,時間復雜度 O(N^2),空間復雜度 O(1)。那麽能做到時間更短嗎?
(2)第二種做法:既然要找左邊的比當前數大的一共有多少個,那麽歸並排序過程中正好是比較左右兩邊的大小,那我們在這個過程中順便統計下左邊比右邊大的數量。
正如上圖所示:
(1)a,b兩步是對數組進行分解
(2)c,d兩步將數組進行合並,我們可以再這個過程中統計 左邊比右邊數大的個數。
我們在統計過程中,將已經合並的按照從小到大的過程進行排序,在合並的過程中,我們只用統計左邊一段,對於右邊一段中每個數產生的逆序對即可,因為不論左邊這段,還是右邊這段,在生成的過程中都是 由 更小的兩個小段 合並而成的,在這個過程中已經統計過了產生的逆序數。
我們圖解一次,統計逆序數量的合並過程。
(1)左右兩個子數組的最後邊出發,取出 7, 6,發現7>6說明,7可以對 4,6產生逆數對,即:左邊這個數 可以對 右邊 沒有遍歷到的其他數均會產生 逆數對,因為 他比這些數都要大,統計 逆數對數量,7放入copy
(2)然後左邊指針 往前走一步,取出:5,6,對於6來說沒有產生逆數對且不能確定6前面的數是否會產生的逆數對,所以將6復制到copy中,
(3)右邊指針往前走一步,取出:5,4,則5對於 右邊沒有遍歷過的數(也就是4和4前面的數)都會產生逆數對,進行統計,然後,將5放入copy
(4)此時 左邊數組元素全部遍歷完成,右邊的剩余元素 全部放入到copy中,此時copy按從小到大排序完成,逆數對統計完成。
class Solution { public: int InversePairs(vector<int> data) { //0個或者1個 if(data.size() == 0 || data.size() == 1) { return 0; } vector<int> copy = data; return sortMergeGetValue(data, copy, 0, data.size() - 1) % 1000000007; } long sortMergeGetValue(vector<int>& data, vector<int>& copy, long l, long r) { if(l >= r) { return 0; } //遞歸調用 歸並排序 long mid = (l + r) /2; long leftCounts = sortMergeGetValue(copy, data, l, mid); long rightCounts = sortMergeGetValue(copy, data, mid + 1, r); long count = 0; long i = mid; //左半端最後面 long j = r; //右半段最後面 long index = r; //copy數組最右邊 //當左右半段還沒有合並完成時,使用while循環 while(i >= l && j > mid) { //判斷左半段 節點是不是 大於 右半段節點,說明左半段這個節點對於 右半段 對應節點 的前面所有節點 都會產生逆數對 if(data[i] > data[j]) { count += (j - mid); copy[index--] = data[i--]; } else { copy[index--] = data[j--]; } } //如果左半段沒有合並完 for(; i>= l; i--) { copy[index--] = data[i]; } //右半段沒有合並完 for(; j > mid; j--) { copy[index--] = data[j]; } return count+ leftCounts + rightCounts; } };
算法復雜度:
時間復雜度:O(N*Log(N))
空間復雜度:O(N)
歸並排序 之 逆序對