问题:
考虑1,2,3...n(n<=100000)的排列,比如263451中含有8个逆序(2,1),(3,1),(4,1),(5,1),(6,3),(6,4),(6,5),(6,1),即大的数在小的数的左边,就构成一个逆序对。
现给定1,2,...n的一个排列,求它的逆序数。
解题策略:
- 笨方法O(n^2)
- 分治O(nlogn)
分治的实现方法:
- 数组分为两半,分别求出左半边和右半边的逆序数
- 再算有多少逆序是由左半边取一个数和右半边取一个数构成(要求O(n)实现)。关键:左右半边都是从大到小排好序的,i,j分别指向左右半边的开始,只需扫一遍就可以找出由两边各取一个数构成的逆序数。
总结:由归并排序改进得到,加上计算逆序的步骤。MergeSortAndCount:归并排序并计算逆序数。
在做之前,先来回顾一下分治的经典应用——归并排序的实现:
def merge_sort(l,start,end):
if start>=end:
return
mid=start+(end-start)//2
merge_sort(l,start,mid)
merge_sort(l,mid+1,end)
merge(l,start,mid,end)
def merge(l,start,mid,end):
temp_l=[]
i,j=start,mid+1
while i<=mid and j<=end:
if l[i]<l[j]:
temp_l.append(l[i])
i+=1
else:
temp_l.append(l[j])
j+=1
temp_l+=l[i:mid+1]
temp_l+=l[j:end+1]