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 0mid = (l + r) // 2res = 0res += mergeSortAndCount(arr, l, mid) + mergeSortAndCount(arr, mid + 1, r)j = mid + 1for i in range(l, mid + 1):while j <= r and nums[j] * 2 < nums[i]:j += 1res += 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 resreturn mergeSortAndCount(nums, 0, len(nums) - 1)
题目分析
分治的思想,一旦想到,应该就比较清晰了。左右sort好之后,只要左右各遍历一遍,就能够得出想要的结果。
一个有趣的地方在于,手写的merge,竟然比直接sort要慢很多,这就很尴尬了。
不过还是有必要记录下来归并的模板,快速写出来,注意题目中条件的判断:
if j > r or (i <= mid and nums[i] <= nums[j])
如果只想写一个ifelse,那么这个条件,i和j的范围都要写好。
另外,提前开一个等大的临时数组存放临时结果,不要递归的时候创建,这样反复创建释放比较费时间。
