問題描述
在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。
輸入: [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/