陣列中的逆序對—Python非歸併解法
題目:在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數。
該問題的最好解法是類似歸併排序的解法,時間複雜度為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)。