【剑指offer】_12 数组中的逆序对
題目描述
在數(shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序?qū)?。輸入一個數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù)P。并將P對1000000007取模的結(jié)果輸出。 即輸出P%1000000007
解題思路
劍指offer的解法
看到這個題目,我們的第一反應(yīng)是順序掃描整個數(shù)組。每掃描到一個數(shù)組的時候,逐個比較該數(shù)字和它后面的數(shù)字的大小。如果后面的數(shù)字比它小,則這兩個數(shù)字就組成了一個逆序?qū)?。假設(shè)數(shù)組中含有n個數(shù)字。由于每個數(shù)字都要和O(n)這個數(shù)字比較,因此這個算法的時間復雜度為O(n^2)。
我們以數(shù)組{7,5,6,4}為例來分析統(tǒng)計逆序?qū)Φ倪^程。每次掃描到一個數(shù)字的時候,我們不拿ta和后面的每一個數(shù)字作比較,否則時間復雜度就是O(n^2),因此我們可以考慮先比較兩個相鄰的數(shù)字。
(a) 把長度為4的數(shù)組分解成兩個長度為2的子數(shù)組;
(b) 把長度為2的數(shù)組分解成兩個成都為1的子數(shù)組;
? 把長度為1的子數(shù)組 合并、排序并統(tǒng)計逆序?qū)?;
(d) 把長度為2的子數(shù)組合并、排序,并統(tǒng)計逆序?qū)?#xff1b;
在上圖(a)和(b)中,我們先把數(shù)組分解成兩個長度為2的子數(shù)組,再把這兩個子數(shù)組分別拆成兩個長度為1的子數(shù)組。接下來一邊合并相鄰的子數(shù)組,一邊統(tǒng)計逆序?qū)Φ臄?shù)目。在第一對長度為1的子數(shù)組{7}、{5}中7大于5,因此(7,5)組成一個逆序?qū)?。同樣在第二對長度為1的子數(shù)組{6}、{4}中也有逆序?qū)?#xff08;6,4)。由于我們已經(jīng)統(tǒng)計了這兩對子數(shù)組內(nèi)部的逆序?qū)?#xff0c;因此需要把這兩對子數(shù)組 排序 如上圖(c)所示, 以免在以后的統(tǒng)計過程中再重復統(tǒng)計。
接下來我們統(tǒng)計兩個長度為2的子數(shù)組子數(shù)組之間的逆序?qū)Α:喜⒆訑?shù)組并統(tǒng)計逆序?qū)Φ倪^程如下圖如下圖所示。
我們先用兩個指針分別指向兩個子數(shù)組的末尾,并每次比較兩個指針指向的數(shù)字。如果第一個子數(shù)組中的數(shù)字大于第二個數(shù)組中的數(shù)字,則構(gòu)成逆序?qū)?#xff0c;并且逆序?qū)Φ臄?shù)目等于第二個子數(shù)組中剩余數(shù)字的個數(shù),如下圖(a)和(c)所示。如果第一個數(shù)組的數(shù)字小于或等于第二個數(shù)組中的數(shù)字,則不構(gòu)成逆序?qū)?#xff0c;如圖b所示。每一次比較的時候,我們都把較大的數(shù)字從后面往前復制到一個輔助數(shù)組中,確保 輔助數(shù)組(記為copy) 中的數(shù)字是遞增排序的。在把較大的數(shù)字復制到輔助數(shù)組之后,把對應(yīng)的指針向前移動一位,接下來進行下一輪比較。
過程:先把數(shù)組分割成子數(shù)組,先統(tǒng)計出子數(shù)組內(nèi)部的逆序?qū)Φ臄?shù)目,然后再統(tǒng)計出兩個相鄰子數(shù)組之間的逆序?qū)Φ臄?shù)目。在統(tǒng)計逆序?qū)Φ倪^程中,還需要對數(shù)組進行排序。如果對排序算法很熟悉,我們不難發(fā)現(xiàn)這個過程實際上就是歸并排序。
代碼實現(xiàn)
class Solution { public:int InversePairs(vector<int> data) {int length=data.size();if(length<=0)return 0;//vector<int> copy=new vector<int>[length];vector<int> copy;for(int i=0;i<length;i++)copy.push_back(data[i]);long long count=InversePairsCore(data,copy,0,length-1);//delete[]copy;return count%1000000007;}long long InversePairsCore(vector<int> &data,vector<int> ©,int start,int end){if(start==end){copy[start]=data[start];return 0;}int length=(end-start)/2;long long left=InversePairsCore(copy,data,start,start+length);long long right=InversePairsCore(copy,data,start+length+1,end); int i=start+length;int j=end;int indexcopy=end;long long count=0;while(i>=start&&j>=start+length+1){if(data[i]>data[j]){copy[indexcopy--]=data[i--];count=count+j-start-length; //count=count+j-(start+length+1)+1;}else{copy[indexcopy--]=data[j--];} }for(;i>=start;i--)copy[indexcopy--]=data[i];for(;j>=start+length+1;j--)copy[indexcopy--]=data[j]; return left+right+count;} };總結(jié)
以上是生活随笔為你收集整理的【剑指offer】_12 数组中的逆序对的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原神披萨食谱在哪里买
- 下一篇: 详解Linux下通过yum安装Maria