逆序數問題 使用歸併排序

2021-08-31 18:52:37 字數 2277 閱讀 6639

在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。

比如3 4 1 2這個陣列有4對逆序:分別是[3,1] [4,1] [3,2] [4,2]。

本文使用歸併排序來求逆序數。

假設歸併排序已經進行到了如上這個狀態,正要把兩個長度為2的有序子串行,合併成乙個長度4的有序序列。

i指向前子串行。j指向後子串行。很明顯,當j指向元素小於i指向元素時,就肯定是產生了逆序對了。而逆序對的個數則與i指向元素在前子串行中的位置有關,是從i開始到前子串行的最後元素的個數(包括i和最後元素來統計),通俗地講,就是如果ji小,那麼j肯定也比i之後的元素還小(當然這裡是指在前子串行中的範圍)。

如上圖,1比3小,那麼1必然也比3後面的元素4小。

def

merge

(start,former,latter,end,src,des)

: gap = end -start +

1 i = start

j = latter

count =

0for step in

range

(gap):if

(i<=former)

and(j<=end)

:if src[i]

<= src[j]

: des[start+step]

= src[i]

i +=

1else

:#只有進入else才代表有逆序對

#j元素比i元素小,那麼j肯定也比前子串行中的i後面的元素小

des[start+step]

= src[j]

j +=

1 count += latter - i#記錄下來前子串行i之後元素個數,包括i

elif

(i<=former)

: des[start+step]

= src[i]

i +=

1elif

(j<=end)

: des[start+step]

= src[j]

j +=

1for step in

range

(gap)

: src[start+step]

= des[start+step]

return count

defmerge_sort

(start,end,src,des)

:if start < end:

count =

0 mid =

(start+end)//2

count += merge_sort(start,mid,src,des)

#加上左子串行的逆序對數

count += merge_sort(mid+

1,end,src,des)

#加上右子串行的逆序對數

count += merge(start,mid,mid+

1,end,src,des)

#再加上左右子串行合併時,發現的逆序對數

return count

return

0#遞迴終點返回0

defcopy_array

(arr)

:return

[none

for i in

range

(len

(arr))]

arr =[9

,8,4

,5,7

,1,3

,6,2

]temp = copy_array(arr)

n =len

(arr)

num = merge_sort(

0,n-

1,arr,temp)

#print(arr)

print

(num)

**改自本人另一篇部落格歸併排序 改進歸併,其中的基本歸併排序的**。

歸併排序 逆序數

對於數列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 ...

求逆序數 逆序數 歸併排序

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