mergesort代码如下:
def merge_lists(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
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]:
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的数组里左右两边都已经排号序,那么这个数组的逆序对只可能是在数组左边取一个和右边取一个组成了。在两个数组merge的过程中,只要一出现左边数组大于右边的情况,就确定了一个逆序对,还可以确定的是在左边数组中该数的左边剩下的数都可以与右边那个数字组成逆序对。
总的逆序对的个数=左侧归并时求的逆序对个数+右侧归并时求得的逆序对个数 + 对整体进行归并时的逆序对个数。
可能会怀疑这三种情况会有重复,但是并没有。左侧归并找到的逆序对相当于从左侧数组中取2
个数,而整体归并的时候是分别从左右数组中取1
个数,不可能发生重复!