歸併排序 求逆序數

2021-07-05 01:27:40 字數 2323 閱讀 9934

首先需要了解逆序對的概念:如果在乙個序列/數列中,滿足

則ax和ay稱為一對逆序對。

現在考慮乙個問題:

對乙個大小為n(即有n個元素)元素隨機無序且唯一的整數序列中,平均有多少個逆序對?

乙個構造證明的方法如下:

設乙個隨機無序且元素唯一的整數序列為

我們令lr為l的反向序列,即

然後在lr中任取兩個數,設為ai和ak,那麼(i小於k)(ai,ak)組成的數對要麼在lr中是逆序對,要麼在l中是逆序對

所以,lr和l中的逆序對總數為

所以,l中逆序對的均值為

也就是說,n個元素的隨機數列中逆序對數是o(n2)。那麼這又有什麼意義呢?

考慮排序問題,在通常公升序排列的規定下,違反有序性質的元素都是某個逆序對的一部分。而基於鄰位交換的排序演算法的目的之一就是消除序列中的逆序對。

這意味著序列中基於鄰位交換排序演算法的時間複雜度和逆序對的數量是成正比的。

這也從另乙個角度證明了基於鄰位交換的排序演算法的期望時間複雜度是平方級別的,典型的比如插入排序和氣泡排序。

演算法:歸併排序是分治法(分而 治之)的一種典型應用,應用遞迴的思想,自頂向下思考:先假定mergesort()可以將乙個亂序的陣列排好序,因此就可以開始」分」(將乙個陣列平均 分成兩部分),再」治」(分別對前後部分呼叫mergesort()使它們有序),最後再寫乙個合併子函式merge(),它可以將兩個有序的數組合 並。merge()實現起來比較容易.只需要管理兩個指標,分別指向兩個子陣列的開頭,開闢新記憶體儲存中間結果,遍歷完兩個陣列就可以完成,時間是θ(n).

假定n個元素的陣列呼叫mergesort()需要時間t(n).因此,t(n)=2t(n/2)+θ(n).由主定理可知:t(n)=θ(nlogn).歸併排序演算法的時間複雜度是θ(nlogn),空間複雜度是θ(n).

求逆序數可以通過管理兩個指標,兩次掃瞄陣列,蠻力法求出,顯然時間複雜度 是θ(n^2).那麼有更快的辦法嗎?答案是肯定的,利用歸併排序法,稍做改進即可.在merge()中,合併兩個已經有序的陣列a,b.因為a.b有 序,所以,a,b各自的逆序數是0,所以ab的逆序數(忽略a、b內部的逆序數)等於a,b之間的逆序數。而a、b內部的逆序數在之前的遞迴中已經求出,加在總的逆序數inversenum中。

舉個例子: a=1,4,6,7,9 b=2,3,5,10,13,21.在merge中發現當前i號元素4比2大,那麼4的逆序數需要+1,又因6,7,9都排在4後面,那麼6,7,9的逆 序數也應該+1,所以總體的逆序數應該加上last-i+1.(如果i號元素比b[j]小(比如4比5小),無法確定逆序數的變化,不作任何修改)。從最下面的含兩個元素的陣列,到上層含多個元素的陣列都有前後之分,這正好與逆序對性質相符,只要我們找出陣列左邊部分的乙個元素a[left_a], 大於 陣列右邊部分某個元素a[left_b] 然後就知道陣列左邊部分在元素a[left_a]之後的元素都應該是大於a[left_b]的。

#include

#include

using

namespace

std;

int inversenum=0;//逆序對數

void merge(int* a,int left,int mid,int right,int* tmp_a)

}while(left_a <= mid) tmp_a[idx_tmp_a++]=a[left_a++];

while(left_b <= right) tmp_a[idx_tmp_a++]=a[left_b++];

//tmp_a已經有序,將tmp_a中資料複製回原陣列a

for(int i=left;i <= right;++i) a[i]=tmp_a[i];

}void mergesort(int* a,int left,int right,int* tmp_a)//假定mergesort能將乙個亂序陣列a排好序.

}int main()

; int len=sizeof(a)/sizeof(a[0]);

int *tmp_a=new

int[len];

mergesort(a,0,len-1,tmp_a);

for(int i=0;icout

cout

return

0;}

參考:

求逆序數 逆序數 歸併排序

求排列的逆序數 分治 一 題目描述 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1...

歸併排序求逆序數

輸入 n 陣列中元素個數 x 最後所存在的每對逆序對所需要花費的錢 y 按任意順序交換陣列中相鄰兩個元素所要花費的錢 n個陣列中元素 輸出 求使陣列變為公升序所需要的最少 即求該陣列的逆序數 按陣列順序 任意順序交換次數均為該陣列的逆序數次 歸併排序求逆序數 歸併排序採用分治策略 ex 重點在於合併...

歸併排序 求逆序數

time limit 50 ms memory limit 65536 kib problem description 對於數列a1,a2,a3 中的任意兩個數ai,aj i j 如果ai aj,那麼我們就說這兩個數構成了乙個逆序對 在乙個數列中逆序對的總數稱之為逆序數,如數列 1 6 3 7 2 ...