https://leetcode.com/problems/reverse-pairs/
很经典的题目。
当然这道题还可以用线段树或者BIT做,不过归并排序在这道题里很经典了。
个人解答
class Solution:
def reversePairs(self, nums: List[int]) -> int:
self.tmp = [0] * len(nums)
def mergeSortAndCount(arr, l, r):
if l >= r:
return 0
mid = (l + r) // 2
res = 0
res += mergeSortAndCount(arr, l, mid) + mergeSortAndCount(arr, mid + 1, r)
j = mid + 1
for i in range(l, mid + 1):
while j <= r and nums[j] * 2 < nums[i]:
j += 1
res += j - (mid + 1)
# merge
# i, j = l, mid + 1
# ti = l
# while ti <= r:
# if j > r or (i <= mid and nums[i] <= nums[j]):
# self.tmp[ti] = nums[i]
# i += 1
# else:
# self.tmp[ti] = nums[j]
# j += 1
# ti += 1
# for i in range(l, r + 1):
# arr[i] = self.tmp[i]
# direct sort, faster than merge???
arr[l:r + 1] = sorted(arr[l:r + 1])
return res
return mergeSortAndCount(nums, 0, len(nums) - 1)
题目分析
分治的思想,一旦想到,应该就比较清晰了。左右sort好之后,只要左右各遍历一遍,就能够得出想要的结果。
一个有趣的地方在于,手写的merge,竟然比直接sort要慢很多,这就很尴尬了。
不过还是有必要记录下来归并的模板,快速写出来,注意题目中条件的判断:
if j > r or (i <= mid and nums[i] <= nums[j])
如果只想写一个ifelse,那么这个条件,i和j的范围都要写好。
另外,提前开一个等大的临时数组存放临时结果,不要递归的时候创建,这样反复创建释放比较费时间。