歸併排序運用 逆序對

2021-10-10 22:59:15 字數 1879 閱讀 9214

假設公升序為預設的序列,在乙個陣列中,陣列的任意一對數字逆序即inum[j],則稱這一數對為逆序數對

給定乙個陣列,求該陣列的逆序數對

陣列中的逆序對

示例:

輸入:

7 5 6 4

5

第一想法是暴力求解,暴力的時間複雜度是o(n^2),會超時

採用歸併排序來優化時間複雜度

歸併排序是通過將陣列分治,再將兩個有序陣列合併,那麼在有序陣列合併的時候就可以展開操作了,具體怎麼做呢?

假設兩個有序的陣列:

3 5 7 9 | 2 4 6 8

第一步合併:

2 3 5 7 9 | 4 6 8

操作開始:當插入2的時候,可以肯定的是2小於[3 5 7 9]中的任何乙個數字

那麼2的逆序數對就有4個,結果+4

第二步合併

2 3

5 7 9 | 4 6 8

操作開始:當插入3的時候,可以肯定的是3小於[4 5 6]中的任何乙個數字

而5 7 9 的位置也在3後面,所以逆序對數為0.結果不變

第三步合併

2 3 4

5 7 9 | 6 8

操作開始:當插入2的時候,可以肯定的是4小於[5 7 9]中的任何乙個數字

那麼2的逆序數對就有3個,結果+3。。

。結果:

2 3 4 5 6 7 8 9

這時候陣列有序了,逆序對數是10

這時候在將 2 3 4 5 6 7 8 9和另乙個陣列1 2 3 4 5 6 7 8 9合併

遵循上面的操作,得出 逆序對數結果 + 10 + 1 2 3 4 5 6 7 8 9]的逆序對結果0

就是兩個陣列合併後陣列的逆序對數

ps(3 5 7 9 和 2 4 6 8的逆序對數均為0)

class

solution

int[

] temp =

newint

[len]

;return

mergesort(0

, len-

1, temp , nums);}

private

intmergesort

(int left,

int right,

int[

] temp,

int[

] nums)

int mid = left+

(right-left)/2

;int left_ans =

mergesort

(left , mid , temp , nums)

;int right_ans =

mergesort

(mid+

1, right , temp , nums)

;int merge_ans =

mergearray

(left , mid , right , temp ,nums)

;return left_ans+right_ans+merge_ans;

//左陣列的逆序對數+合併計算的逆序對數+右陣列的逆序對數

}private

intmergearray

(int left,

int mid,

int right,

int[

] temp,

int[

] nums)

else

if(j==right+1)

else

if(temp[i]

<=temp[j]

)else

}return count;

}}

逆序對 (歸併排序)

逆序對的nlogn方法,改進後的歸併排序 給定排列p,求排列的逆序對數量。p的長度 100000。要求o nlogn 定義歸併排序過程merge l,r merge l,r merge l,mid merge mid 1,r count l,mid,mid 1,r 只需要考慮左右兩段之間造成的逆序對...

歸併排序 逆序對

按照劉汝佳說的,歸併排序分三步 1.劃分問題,即把序列分成元素盡量相等的兩半 2.遞迴求解 3.合併子問題 其實就是把乙個序列不斷的二分,直到只有兩個元素的時候,然後排序,然後返回,再排序。先上 include using namespace std long long a 100005 t 100...

歸併排序(逆序對)

現在我們在競賽中最常用的排序是快速排序,c 只要乙個sort就搞定,但非常明顯,歸併排序的時間複雜度是最優的而且非常穩定,但是人們經常把它用在求逆序對個數上面。那麼下面我用乙個這樣的題來講一下歸併排序。點這裡看題目和樹狀陣列解法。歸併排序是將數列a l,h 分成兩半a l,mid 和a mid 1,...