题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
思路
暴力法是两个for循环遍历数组,比较数组中的每一对数字,但是会超时。
如何减少比较次数?
利用归并排序的思想。
原数组: [7,5,6,4]
一分为二:left = [7,5],right = [6,4]
对每个子数组排序:left = [5,7],right = [4,6]
归并的过程中寻找逆序对:
left中的第一个元素5大于right中的第一个元素4,可以构成一个逆序对。由于两个子数组都是排好序的,所以5后面的元素都大于4,可以不再进行比较就能确定,都可以和4构成逆序对。
在归并排序的基础上添加统计逆序对个数即可。
代码
class Solution:
def reversePairs(self, nums: List[int]) -> int:
self.count = 0
def Merge(left, right, s):
i, j, k = 0, 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
s[k] = left[i]
i += 1
k += 1
else:
self.count += len(left)-i
s[k] = right[j]
j += 1
k += 1
while i < len(left):
s[k] = left[i]
i += 1
k += 1
while j < len(right):
s[k] = right[j]
j += 1
k += 1
def MergeSort(nums):
if len(nums) < 2:
return nums
mid = len(nums)//2
left = nums[:mid]
right = nums[mid:]
MergeSort(left)
MergeSort(right)
Merge(left, right, nums)
MergeSort(nums)
return self.count
复杂度
时间复杂度: O(nlogn)
空间复杂度: O(n)