【LeetCode】面試題51 逆序對

問題描述

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

輸入: [7,5,6,4]
輸出: 5

限制: 0 <= 數組長度 <= 50000

問題分解

先用僞代碼再現問題中的邏輯

if arr[i] > arr[j] and i < j , 則生成一個逆序對 n[i][j]

可推 : 拿出數組中的一個元素,對比之後的元素,只要大於之後的值,那麼總數+1 ,這樣得出來的就是暴力法

但是,顯然暴力法是不可取的,因爲會造成算法的超時

問題解決

歸併排序

當歸並排序執行合併數組的時候,可以比較兩個數組指針對應的值,得出對應數組分別滿足題目的數量,這樣做相比暴力破解法可以大幅度降低執行時間。

具體解法參考下面代碼,已經加了註釋。

class Solution:
    def mergeSort(self, nums, tmp, l, r):
        if l >= r:
            return 0 #拆分到頭
        mid = (l + r) // 2 # 找到中心段
        inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r) #並操作
        i, j, pos = l, mid + 1, l
        while i <= mid and j <= r: 
            if nums[i] <= nums[j]:  # 進行數據比對,滿足條件就增加計數
                tmp[pos] = nums[i]
                i += 1
                inv_count += (j - (mid + 1))
            else:
                tmp[pos] = nums[j]
                j += 1
            pos += 1
        for k in range(i, mid + 1):
            tmp[pos] = nums[k]
            inv_count += (j - (mid + 1))
            pos += 1
        for k in range(j, r + 1):
            tmp[pos] = nums[k]
            pos += 1
        nums[l:r+1] = tmp[l:r+1] 
        return inv_count

    def reversePairs(self, nums: List[int]) -> int: # 開始
        n = len(nums) # 得到數組長度
        tmp = [0] * n # 定義0填充的數組作爲臨時空間
        return self.mergeSort(nums, tmp, 0, n - 1) # 執行遞歸方法

參考資料

  • https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
  • https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/shu-zu-zhong-de-ni-xu-dui-by-leetcode-solution/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章