面试题36:数组中的逆序对
生活随笔
收集整理的這篇文章主要介紹了
面试题36:数组中的逆序对
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目:在數(shù)組中的兩個數(shù)字如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序?qū)Α]斎胍粋€數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù)。例如,有一個數(shù)組為Array[0..n] 其中有元素a[i],a[j].如果 當i<j時,a[i]>a[j],那么我們就稱(a[i],a[j])為一個逆序?qū)ΑT跀?shù)組{7,5,6,4}中一共存在5對逆序?qū)?#xff0c;分別是(7,6),(7,5),(7,4),(6,4),(5,4)。 如果arry[i]>arry[j],因為兩段數(shù)組都是有序的,所以arry[i]>arry[mid+1...j],這些都是逆序?qū)?#xff0c;我們統(tǒng)計出的逆序?qū)閖-(mid+1)+1=j-mid。并且將大數(shù)arry[i]放入臨時數(shù)組temp[]當中,i往前移動 如果arry[i]<arry[j],則將大數(shù)arry[j]放入temp[]中,j往前移。
參考文獻
排序算法匯總->歸并排序
解題思路
看到這樣的題目,最簡單的想法就是遍歷每一個元素,讓其與后面的元素對比,如果大于則count++,但是這樣的時間復雜度是o(n2)。這題有更好的解決方法,時間復雜度只需要o(nlogn)。其實這道題目的思路跟歸并排序差不多,求逆序?qū)Φ倪^程就是一個求歸并排序的過程,在求出逆序?qū)σ院?#xff0c;原數(shù)組變得有序,是通過歸并排序得到的。
(1)總體的意思就是將數(shù)組分成兩段,首先求段內(nèi)的逆序?qū)?shù)量,比如下面兩段代碼就是求左右兩端數(shù)組段內(nèi)的逆序?qū)?shù)量
inversions+=InversePairsCore(arry,start,mid,temp);//找左半段的逆序?qū)?shù)目 inversions+=InversePairsCore(arry,mid+1,end,temp);//找右半段的逆序?qū)?shù)目(2)然后求段間的逆序?qū)?shù)量,如下面的代碼
inversions+=MergeArray(arry,start,mid,end,temp);//在找完左右半段逆序?qū)σ院髢啥螖?shù)組有序,然后找兩段之間的逆序?qū)ΑW钚〉哪嫘蚨沃挥幸粋€元素。(3)然后在求段間逆序?qū)Φ臅r候,我們分為arry[start...mid]和arry[mid+1...end],然后設置兩個指針ij分別指向兩段數(shù)組的末尾元素,也就是i=mid,j=end。然后比較arry[i]和arry[j],
完整實現(xiàn)代碼
View Code #include<iostream> #include<stdlib.h> using namespace std;void printArray(int arry[],int len) {for(int i=0;i<len;i++)cout<<arry[i]<<" ";cout<<endl; } int MergeArray(int arry[],int start,int mid,int end,int temp[])//數(shù)組的歸并操作 {//int leftLen=mid-start+1;//arry[start...mid]左半段長度//int rightLlen=end-mid;//arry[mid+1...end]右半段長度int i=mid;int j=end;int k=0;//臨時數(shù)組末尾坐標int count=0;//設定兩個指針ij分別指向兩段有序數(shù)組的頭元素,將小的那一個放入到臨時數(shù)組中去。while(i>=start&&j>mid){if(arry[i]>arry[j]){temp[k++]=arry[i--];//從臨時數(shù)組的最后一個位置開始排序count+=j-mid;//因為arry[mid+1...j...end]是有序的,如果arry[i]>arry[j],那么也大于arry[j]之前的元素,從a[mid+1...j]一共有j-(mid+1)+1=j-mid }else{temp[k++]=arry[j--];}}cout<<"調(diào)用MergeArray時的count:"<<count<<endl;while(i>=start)//表示前半段數(shù)組中還有元素未放入臨時數(shù)組 {temp[k++]=arry[i--];}while(j>mid){temp[k++]=arry[j--];}//將臨時數(shù)組中的元素寫回到原數(shù)組當中去。for(i=0;i<k;i++)arry[end-i]=temp[i];printArray(arry,8);//輸出進過一次歸并以后的數(shù)組,用于理解整體過程return count;}int InversePairsCore(int arry[],int start,int end,int temp[]) {int inversions = 0; if(start<end){int mid=(start+end)/2;inversions+=InversePairsCore(arry,start,mid,temp);//找左半段的逆序?qū)?shù)目inversions+=InversePairsCore(arry,mid+1,end,temp);//找右半段的逆序?qū)?shù)目inversions+=MergeArray(arry,start,mid,end,temp);//在找完左右半段逆序?qū)σ院髢啥螖?shù)組有序,然后找兩段之間的逆序?qū)ΑW钚〉哪嫘蚨沃挥幸粋€元素。 } return inversions; }int InversePairs(int arry[],int len) {int *temp=new int[len];int count=InversePairsCore(arry,0,len-1,temp);delete[] temp;return count; }void main() {//int arry[]={7,5,6,4};int arry[]={1,3,7,8,2,4,6,5};int len=sizeof(arry)/sizeof(int);//printArray(arry,len);int count=InversePairs(arry,len);//printArray(arry,len);//cout<<count<<endl;system("pause"); }?輸出結(jié)果:
調(diào)用MergeArray時的count:0 1 3 7 8 2 4 6 5 調(diào)用MergeArray時的count:0 1 3 7 8 2 4 6 5 調(diào)用MergeArray時的count:0 1 3 7 8 2 4 6 5 調(diào)用MergeArray時的count:0 1 3 7 8 2 4 6 5 調(diào)用MergeArray時的count:1//這是因為上面65之間有段內(nèi)的逆序?qū)?/span> 1 3 7 8 2 4 5 6 調(diào)用MergeArray時的count:0 1 3 7 8 2 4 5 6 調(diào)用MergeArray時的count:9//這里全部都是段間的逆序?qū)?#xff0c;(3,2),(7,2),(7,4),(7,5),(7,6),(8,2),(8,4),(8,5),(8,6),一共有九個 1 2 3 4 5 6 7 8 逆序?qū)?shù)量:10?
?
總結(jié)
以上是生活随笔為你收集整理的面试题36:数组中的逆序对的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#如何用Graphics画出一幅图表
- 下一篇: onbeforeunload与onunl