在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
解题模板:
class Solution:
def reversePairs(self, nums: List[int]) -> int:
暴力解题的做法不提倡,时间复杂度O(N^2)。这里用到分治的思想解题,有关排序问题应用分治思想的方法,归并排序是很好的例子。将整个问题简化,递归地解决简单问题,从而实现复杂问题的攻克。
如官方所给的例子:
对于本题来说,数列的逆序数计算也可以一步步地分而治之
首先给出归并排序的代码:
def mergesort(nums, tmp, left, right):
if left >= right:
return
mid = (right + left) // 2
mergesort(nums, tmp, left, mid)
mergesort(nums, tmp, mid+1, right)
# 这里采用后序遍历(左→右→根)的方法
i = left
j = mid + 1
k = left
while i <= mid and j <= right:
if nums[i] <= nums[j]:
tmp[k] = nums[i]
k += 1
i += 1
else:
tmp[k] = nums[j]
k += 1
j += 1
while i <= mid:
tmp[k] = nums[i]
k += 1
i += 1
while j <= right:
tmp[k] = nums[j]
k += 1
j += 1
for i in range(left, right+1):
nums[i] = tmp[i]
tmp = [0] * len(nums)
mergesort(nums, tmp, 0, len(nums)-1)
时间复杂度O(N*logN),归并排序虽然不是排序算法中效率最高的,不过其分治的思想很重要!
class Solution:
def reversePairs(self, nums: List[int]) -> List[int]:
tmp = [0] * len(nums)
def mergesort(nums, tmp, left, right):
if left >= right:
return 0
mid = (right + left) // 2
sum_ = mergesort(nums, tmp, left, mid)
sum_ += mergesort(nums, tmp, mid+1, right)
# 这里增加了计数器
i = left
j = mid + 1
k = left
while i <= mid and j <= right:
if nums[i] <= nums[j]:
tmp[k] = nums[i]
k += 1
i += 1
else:
tmp[k] = nums[j]
sum_ += mid - i + 1 # 统计失序数对的数量
k += 1
j += 1
while i <= mid:
tmp[k] = nums[i]
k += 1
i += 1
while j <= right:
tmp[k] = nums[j]
k += 1
j += 1
for i in range(left, right+1):
nums[i] = tmp[i]
return sum_
sum_ = mergesort(nums, tmp, 0, len(nums)-1)
return sum_
时间复杂度O(N*logN)