利用歸併排序求解逆序數及其時間複雜度分析

2021-08-28 10:16:11 字數 1096 閱讀 7759

part 1:問題描述

在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。現在給定乙個序列,其中元素皆為整數(當然,這裡只是為了方便,實際上也可以是其他型別的資料),元素個數未知,要求給出其逆序數。

part 2:求解思路

1.由於元素個數未知,可以使用vector,能實現元素的快速增長。

2.從歸併排序出發,只需做一點小改動即可得出逆序數。具體來說,歸併排序要做的是:讓兩個子串行分別有序(使用遞迴函式),再將這兩個排好序的子串行合併成乙個有序的序列。假設我們要將序列從小到大排列,那麼在合併(merge)的過程裡,每當我們從第乙個序列取出乙個數放到合成的序列中時,這個數相對於第二個序列裡剩餘的數而言,都不構成逆序;反之,當我們從第二個序列裡取出乙個數放到合成序列中時,這個數相對於第乙個序列裡剩餘的所有數,都分別構成乙個逆序對。

part 3:**實現

時間複雜度分析:

而在一般情形,輸入n個數的序列,要對兩個長度為n/2的子串行分別進行一次歸併排序並計算其中逆序數,花費時間為2*t(n/2),隨後要對這兩個子串行進行合併。合併時,首先要進行至多n次比較,每次比較至少使得合併序列的元素增加乙個,同時如果是從第二個子串行拿元素,要對cnt的值進行一次加法運算。最後,要把合併序列的n個元素的值複製到原序列。不難分析出這些操作花費o(n).

綜上,有公式:t(n)=2*t(n/2)+n.  再假設n/2可以被2整除,那麼就有: t(n/2)=2t(n/4)+n/2 

聯立後:t(n)=4t(n/4)+2n

假設n是2的k次冪,那麼這個過程可以一直持續下去,得到:

t(n)=8t(n/8)+3n=......=(2^k)*t(n/2^k)+kn

有k=logn 有:t(n)=n logn + n

因此該方法的時間複雜度是o(n logn).

分治法求解逆序數 歸併排序

題目內容 設a1,a2,an是集合的乙個排列,如果iaj,則序偶 ai,aj 稱為該排列的乙個逆序。例如,2,3,1有兩個逆序 3,1 和 2,1 設計演算法統計給定排列中含有逆序的個數。輸入格式 第一行輸入集合中元素個數n,第二行輸入n個集合元素 輸出格式 含有逆序的個數 輸入樣例 32 3 1 ...

歸併排序 逆序數

對於數列a,將其二分地拆分為b,c 先將b,c分別排序好,再合併b,c即為總的排序,不過在合併的過程中我們可以算出逆序數哦。其原理網上很多,我這裡不再贅述,只給出實現 include include define ll long long using namespace std ll mergeso...

逆序數(歸併排序)

分而治之 分 每次從中間劃分開,直到有序為止,即乙個整數 void merge int s,int left,int right 治重新定義乙個a陣列,儲存排序完的合併陣列,void sort int s,int left,int mid,int right while i mid a k s i ...