题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
解题思路
利用归并排序算法,在合并两个子序列的时候统计逆序对个数。
复杂度分析:
时间复杂度:O(NlogN),这里 N 是数组的长度。复杂度是归并排序的时间复杂度,直接看递归树的结点个数或者使用主定理分析,归并的回收每一步计算逆序对的个数是 O(1) 的;
空间复杂度:O(N)。
代码
class Solution:
# 在数组 nums 的区间 [left, right] 统计逆序对
def count_reverse_pairs(self, nums, left, right, tmp):
if left == right:
return 0
mid = left + (right-left)//2
left_cnt = self.count_reverse_pairs(nums, left, mid, tmp)
right_cnt = self.count_reverse_pairs(nums, mid+1, right, tmp)
if nums[mid]<=nums[mid+1]:
# 即整个数组已经有序,则无需合并,所以不用计算横跨两个区间的逆序对,直接返回
return left_cnt + right_cnt
merge_cnt = self.merge_and_count(nums, left, mid, right, tmp)
return left_cnt + merge_cnt + right_cnt
def merge_and_count(self, nums, left, mid, right, tmp):
# [left, mid] 有序,[mid + 1, right] 有序
for i in range(left, right+1):
tmp[i] = nums[i]
i = left
j = mid+1
count = 0
for k in range(left, right + 1):
if i > mid:
nums[k] = tmp[j]
j += 1
elif j > right:
nums[k] = tmp[i]
i += 1
elif tmp[i] <= tmp[j]:
# 此时前数组元素出列,不统计逆序对
nums[k] = tmp[i]
i += 1
else:
# 此时后数组元素出列,统计逆序对
nums[k] = tmp[j]
j += 1
count += (mid - i + 1)
return count
def reversePairs(self, nums: List[int]) -> int:
n = len(nums)
if n<2:
return 0
# 用于归并的辅助数组
tmp = [0]*n
return self.count_reverse_pairs(nums, 0, n-1, tmp)