在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。
示例 1:
輸入: [7,5,6,4]
輸出: 5
限制:
0 <= 數組長度 <= 50000
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
思路:歸併排序
在歸併排序的基礎上進行統計,可以發現需要歸併的兩個區間,如果需要排序則是逆序的,也就是我們需要統計的次數。
官方題解(帶視頻)
class Solution:
def reversePairs(self, nums: List[int]) -> int:
length = len(nums)
# 輔助數組,傳遞過去的話,就只申請了一次空間
temp = [0] * length
return self.merger(nums, 0, length-1, temp)
# 歸併排序
def merger(self, nums, left, right, temp):
# print(left, right)
if left >= right:
return 0
mid = left + ((right - left) >> 1)
# print(left, right, mid)
cnt_left = self.merger(nums, left, mid, temp)
cnt_right = self.merger(nums, mid+1, right, temp)
# 檢測是否需要合併(兩個區間是否可以直接有序):
if nums[mid] <= nums[mid+1]:
return cnt_left + cnt_right
# 合併:
temp[left:right+1] = nums[left:right+1] # 複製時不要複製整個數組
i = left
j = mid + 1
k = left
cnt_merger = 0
while i <= mid and j <= right:
if temp[i] <= temp[j]:
nums[k] = temp[i]
k += 1
i += 1
else:
nums[k] = temp[j]
cnt_merger += mid - i + 1
k += 1
j += 1
# 左區間是否全部放入temp:
if i <= mid:
while i <= mid:
nums[k] = temp[i]
k += 1
i += 1
# 右區間是否全部放入temp:
if j <= right:
while j <= right:
nums[k] = temp[j]
k += 1
j += 1
return cnt_left + cnt_right + cnt_merger