歸併排序應用之求陣列中的逆序數

2021-09-22 09:48:37 字數 2306 閱讀 1781

一,問題描述

給定乙個陣列,求解該陣列中有多少組逆序對。比如 [7,5,6,4]一共有五對逆序對。分別是:(7,6),(7,5),(7,4),(6,4),(5,4)

二,演算法分析

有兩種方法來求解逆序對 的數目。一種是,對陣列中的每個元素,都與它後面的元素進行比較,若後面的元素比它小,則找到乙個逆序對。

這樣,第乙個元素與後面的n-1個元素比較,一共比較 n-1 次,第二個元素比較 n-2次,.....故一共需要比較  n(n+1)/2 次。時間複雜度為o(n^2)

另一種方式則是借助排序。試想,某些排序演算法(歸併、快速排序)只需要o(nlogn)就把整個陣列排好序了,那能不能利用排序來求逆序對 的數目?

其實,排序過程,就是乙個不斷地消除逆序對 的過程。對於有序陣列,它的逆序對為0。

而對於消除逆序對,在歸併排序中,合併兩個有序子陣列的過程 就是乙個消除逆序對的過程。

關於歸併排序可參考:

因此,只需要對歸併排序中的合併過程稍做修改,就可以求解逆序對的數目了。

三,**實現及分析

1

public

class inversepairs 9//

類似於歸併排序中的 遞迴分解陣列

10private

static

int inversepairs(int arr, int tmparr, int left, int right)

20return 0;//

left==right 意味著子陣列中只有乙個元素.逆序對數目當然為0

21 }

22//

類似於 歸併排序中的 合併兩個有序子陣列

23private

static

int merge(int arr, int tmparr, int leftpos,

24int rightpos, int rightend) else

37 }

3839

while (leftpos <= leftend)

40 tmparr[tmppos++] = arr[leftpos++];

41while (rightpos <= rightend)

42 tmparr[tmppos++] = arr[rightpos++];

4344

for (int i = 0; i < numelements; i++, rightend--)

45 arr[rightend] = tmparr[rightend];

46return inversecount;

47 }

48//

for test purpose

49public

static

void main(string args) ;

51int result = inversepairs(arr);

52 system.out.println(result);

53 }

54 }

其實,上面整個過程 與歸併排序的實現非常的相似。最重要的是第32行,計算逆序對數目。(與歸併排序比較,最主要的變化的也是第32行)

當 merge 兩個 陣列時:請注意,這兩個陣列是有序的。因此,逆序對的數目計算公式為:leftend - leftpos + 1

比如,如下示例:對於 5 而言,比4大。這說明 5 後面的元素都比 4 大。因此,對於 4 而言有 (5,4) (7,4)兩個逆序對。

另外,第15行-17行,也是對遞迴的理解(歸併排序是乙個遞迴過程,計算逆序對數目 也是乙個遞迴過程)

int leftpairs = inversepairs(arr, tmparr, left, center);//左半部分陣列的逆序對數目

int rightpairs = inversepairs(arr, tmparr, center + 1, right);//右半部分陣列的逆序對數目

currentpairs = merge(arr, tmparr, left, center + 1, right);//合併左右部分陣列時,消除的逆序對數目

return leftpairs + rightpairs + currentpairs;//最終返回 總的逆序對 的數目

四,參考資料

歸併排序應用之陣列中的逆序對數

在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。輸入 7,5,6,4 輸出 5 class solution def init self self.count 0def reversepairs self,nums list...

歸併排序求陣列中的逆序對

描述 測試說明與提交 提交狀態 題目設定 給定一組數,其中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數。首先輸入資料組數t 1 t 100 每組測試資料報括兩行 第一行包含乙個整數n,表示陣列中的元素個數。其中1 n 10 5。第...

歸併排序 逆序數

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