1. 程式人生 > >陣列中的逆序對—Python非歸併解法

陣列中的逆序對—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)。