之因此將標題中三者放一塊兒是由於它們有密不可分的關係.python
def merge_ordered_list(left, right): res = [] lc = rc = 0 while lc < len(left) and rc < len(right): if left[lc] <= right[rc]: res.append(left[lc]) lc += 1 else: res.append(right[rc]) rc += 1 res.extend(left[lc:]) res.extend(right[rc:]) return res
由以上代碼段能夠看出,合併過程當中只對左右列表分別進行了一遍歷,所以時間複雜度爲 O(n)
app
歸併排序分爲兩步:code
merge_ordered_list
.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_ordered_list(left, right)
由於每次都是平均分的,所以將一個長度爲 n 的列表分爲 n 個長度爲 1 的子列表須要lg(n)
次操做(能夠將拆分過程想象爲樹的分叉),所以merge_sort
需遞歸調用 n 次;
又由於每次調用的時間複雜度爲O(n)
,故整個過程的時間複雜度爲O(nlg(n))
排序
若是採用暴力求解,分別求每一個元素逆序對,須要兩兩比較列列表中的元素,時間複雜度爲 O(n**2)
;
結合歸併排序能夠將時間複雜度降爲O(nlg(n))
;遞歸
在第一節合併有序列表
第三步中,rc 指向元素right[rc]
小於 lc 指向元素left[lc]
時, left[lc:]
中的每一個元素都和right[rc]
組成了逆序對,由此可得出逆序對個數,代碼以下:it
對merge_ordered_list
進行稍許修改,記錄逆序對個數.io
inversion_count = 0 def merge_ordered_list(left, right): global inversion_count res = [] lc = rc = 0 while lc < len(left) and rc < len(right): if left[lc] <= right[rc]: res.append(left[lc]) lc += 1 else: res.append(right[rc]) rc += 1 # 統計逆序對個數 inversion_count += len(left[lc:]) res.extend(left[lc:]) res.extend(right[rc:]) return res
這時調用merge_sort
會同時得出li中逆序對個數,時間複雜度爲歸併排序的複雜度O(nlg(n))
.class