陣列中的逆序對

2021-08-11 12:53:41 字數 2375 閱讀 5195

這道程式設計題很不錯,於是就記錄下來了,主要知識點是歸併排序

題目:在陣列中的兩個數字如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。

例如,有乙個陣列為array[0..n]其中有元素a[i],a[j].如果當i<j時,a[i]>a[j],那麼我們就稱(a[i],a[j])為乙個逆序對。在陣列中一共存在5對逆序對,分別是(7,6),(7,5),(7,4),(6,4),(5,4)。

解題思路

看到這樣的題目,最簡單的想法就是遍歷每乙個元素,讓其與後面的元素對比,如果大於則count++,但是這樣的時間複雜度是o(n2)。這題有更好的解決方法,時間複雜度只需要o(nlogn)。其實這道題目的思路跟歸併排序差不多,求逆序對的過程就是乙個求歸併排序的過程,在求出逆序對以後,原陣列變得有序,是通過歸併排序得到的。

(1)總體的意思就是將陣列分成兩段,首先求段內的逆序對數量,比如下面兩段**就是求左右兩端陣列段內的逆序對數量

inversions+=inversepairscore(arry,start,mid,temp);

//找左半段的逆序對數目

inversions+=inversepairscore(arry,mid+1,end,temp);

//找右半段的逆序對數目

(2)然後求段間的逆序對數量,如下面的**

inversions+=mergearray(arry,start,mid,end,temp);

//在找完左右半段逆序對以後兩段陣列有序,然後找兩段之間的逆序對。最小的逆序段只有乙個元素。

(3)然後在求段間逆序對的時候,我們分為arry[start…mid]和arry[mid+1…end],然後設定兩個指標ij分別指向兩段陣列的末尾元素,也就是i=mid,j=end。然後比較arry[i]和arry[j],

完整**(c/c++)

#include

#include

using

namespace

std;

void printarray(int arry,int len)

else

}cout

<<"呼叫mergearray時的count:"

=start)//表示前半段陣列中還有元素未放入臨時陣列

while(j>mid)

//將臨時陣列中的元素寫回到原陣列當中去。

for(i=0;i8);//輸出進過一次歸併以後的陣列,用於理解整體過程

return count;

}int inversepairscore(int arry,int start,int end,int temp)

return inversions;

}int inversepairs(int arry,int len)

void main()

;int arry=;

int len=sizeof(arry)/sizeof(int);

//printarray(arry,len);

int count=inversepairs(arry,len);

//printarray(arry,len);

//cout}

輸出結果

呼叫mergearray時的count:037

8246

5呼叫mergearray時的count:037

8246

5呼叫mergearray時的count:037

8246

5呼叫mergearray時的count:037

8246

5呼叫mergearray時的count:1

//這是因為上面65之間有段內的逆序對37

8245

6呼叫mergearray時的count:037

8245

6呼叫mergearray時的count:9

//這裡全部都是段間的逆序對,(3,2),(7,2),(7,4),(7,5),(7,6),(8,2),(8,4),(8,5),(8,6),一共有九個23

4567

8逆序對數量:10

小結

這種解法確實十分的精彩,通過前面的討論,可以總結如下:先把陣列分隔成子陣列,先統計出子陣列內部的逆序對的數目,然後再統計出兩個相鄰子陣列之間的逆序對的數目。在統計逆序對的過程中,還需要對陣列進行排序,實質上就是歸併排序。

陣列中逆序對

題目 在陣列中的兩個數字,如果前面的乙個數字大於後面的數字,則這兩個數字為乙個逆序對。輸入乙個陣列,求這個陣列的逆序對個數。例如 給定陣列 則有 5,3 5,1 8,3 8,1 3,1 這5個逆序對。問題分析 我採用兩種方法來解決這個問題 1 考慮到二叉搜尋樹中每個節點x,它的左子樹所有關鍵字的值小...

陣列中的逆序對

來自劍指offer 分析 我們第一反應是順序掃瞄整個陣列,每掃瞄到乙個數字時,逐個比較該數字和它後面的數字的大小。如果後面的數字比它小,則這個兩個數字就組成了乙個逆序對。假設陣列有n個數字,由於每個數字都要和o n 個數字作比較,因此這個演算法的時間複雜度為o n 2 換思路 我們採用歸併思想,先考...

陣列中的逆序對

題目 在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。用歸併排序演算法,歸併的時候,從後向前歸併。include using namespace std int getreversenum int p1,int p2,int...