题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
该问题的最好解法是类似归并排序的解法,时间复杂度为O(nlogn),网上相关介绍博客也很多,这里给出一个非归并解法,复杂度会高一点,但想法非常巧妙,代码非常简易。
以一个例子来说明:
输入数组:data=[3,2,1,5,4,6,0,7]
排序好数组:dataSorted=[0,1,2,3,4,5,6,7]
顺序遍历dataSorted数组,第一个元素0是最小的元素,因此在data数组中,0前面有多少个数,就有多少个逆序对。在0检测完之后,将0从data数组中删除,data=[3,2,1,5,4,6,7],dataSorted数组遍历到1,而1其实就是[1,2,3,4,5,6,7]中的最小元素
因此,原问题就变为子问题:
输入数组:data=[3,2,1,5,4,6,7]
排序好数组:dataSorted=[1,2,3,4,5,6,7]
……
重复上述步骤直到遍历到最后一个元素。
函数代码如下:
def InversePairs(data):
count = 0
copy = [i for i in data]
copy.sort()
for i in range(len(copy)):
count += data.index(copy[i])
data.remove(copy[i])
return count
注意第三行不能直接copy = data,因为这样是浅复制,他只是将原有的data数组打上一个新标签,所以当其中一个标签被改变的时候,数组就会发生变化,另一个标签也会随之改变。
而用copy = [i for i in data]相当于深复制,即将原数组重新复制一份给copy,两者就不会相互影响了,但需要多一份数组的内存空间,而浅复制不会重新占用空间。
复杂度分析:
sort排序复杂度为O(nlogn);单次index查找复杂度为O(lgn),要查找n次,复杂度也为O(nlogn);单次remove操作中:查找该数的复杂度为O(lgn),移动该数后面的数复杂度为O(n),因此复杂度为O(n),要remove操作n次,复杂度为O(n^2);因此总的复杂度为O(n^2)。