之因此将标题中三者放一块儿是由于它们有密不可分的关系.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