mergesort**如下:
def merge_lists(left, right):
res =
lc = rc = 0
while lc < len(left) and rc < len(right):
if left[lc] <= right[rc]:
lc += 1
else:
rc += 1
res.extend(left[lc:])
res.extend(right[rc:])
return res
def merge_sort(li):
if len(li) == 1:
return li
# split
mid_index = len(li) // 2
left = merge_sort(li[:mid_index])
right = merge_sort(li[mid_index:])
# merge
return merge_lists(left, right)
merge的過程裡可以統計逆序對的個數。
inversion_count = 0
def merge_lists(left, right):
global inversion_count
res =
lc = rc = 0
while lc < len(left) and rc < len(right):
if left[lc] <= right[rc]:
lc += 1
else:
rc += 1
# 統計逆序對個數
inversion_count += len(left[lc:])
res.extend(left[lc:])
res.extend(right[rc:])
return res
假設正在merge的陣列裡左右兩邊都已經排號序,那麼這個陣列的逆序對只可能是在陣列左邊取乙個和右邊取乙個組成了。在兩個陣列merge的過程中,只要一出現左邊陣列大於右邊的情況,就確定了乙個逆序對,還可以確定的是在左邊陣列中該數的左邊剩下的數都可以與右邊那個數字組成逆序對。
總的逆序對的個數=左側歸併時求的逆序對個數+右側歸併時求得的逆序對個數 + 對整體進行歸併時的逆序對個數。
可能會懷疑這三種情況會有重複,但是並沒有。左側歸併找到的逆序對相當於從左側陣列中取2
個數,而整體歸併的時候是分別從左右陣列中取1
個數,不可能發生重複!
逆序對的個數
對於陣列a 1.n 若有ia j 則對偶 i,j 稱為a的乙個逆序對。求陣列中逆序對個數,很簡單的思路是每個數和後面的數比較,這樣需要 n 2 的時間,如果採用歸併排序的思想最壞情況下需要o nlgn 1.分解a low.mid 和a mid 1.high 2.求解 3.合併,陣列a low.mid...
逆序對的個數
在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數p。並將p對1000000007取模的結果輸出。即輸出p 100000000 include include include include includeusing names...
分治 求逆序對個數並列印逆序對
如果用最hick的方法去求那麼就是o n 2 的複雜度,如果想優化的話,用歸併排序的方法分治處理。主要思想 總逆序 左邊逆序 右邊逆序 左邊右邊分別排序後的逆序 include includeusing namespace std 用歸併排序的思想來求,歸併排序為o nlogn 的時間複雜度,比暴力...