#### [leetcode 493 翻转对](https://leetcode-cn.com/problems/reverse-pairs/) > 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈 > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 > > 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 **题目描述** 给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。 你需要返回给定数组中的重要翻转对的数量。 示例 1: > 输入: [1,3,2,3,1] > 输出: 2 示例 2: > 输入: [2,4,3,5,1] > 输出: 3 **题目解析** 我们理解了逆序对的含义之后,题目理解起来完全没有压力的,这个题目第一想法可能就是用暴力法解决,但是会超时,所以我们有没有办法利用归并排序来完成呢? 我们继续回顾一下归并排序的归并过程,两个小集合是有序的,然后我们需要将小集合归并到大集合中,则我们完全可以在归并之前,先统计一下翻转对的个数,然后再进行归并,则最后排序完成之后自然也就得出了翻转对的个数。具体过程见下图。 ![翻转对](https://cdn.jsdelivr.net/gh/tan45du/test1@master/20210122/微信截图_20210214121010.50g9z0xgda80.png) 此时我们发现 6 > 2 * 2,所以此时是符合情况的,因为小数组是单调递增的,所以 6 后面的元素都符合条件,所以我们 count += mid - temp1 + 1;则我们需要移动紫色指针,判断后面是否还存在符合条件的情况。 ![翻转对](https://cdn.jsdelivr.net/gh/tan45du/test1@master/20210122/微信截图_20210214121711.77crljdzra00.png) 我们此时发现 6 = 3 * 2,不符合情况,因为小数组都是完全有序的,所以我们可以移动红色指针,看下后面的数有没有符合条件的情况。这样我们就可以得到翻转对的数目啦。下面我们直接看动图加深下印象吧! ![](https://img-blog.csdnimg.cn/20210317192545806.gif#pic_center) 是不是很容易理解啊,那我们直接看代码吧,仅仅是在归并排序的基础上加了几行代码。 Java Code: ```java class Solution { private int count; public int reversePairs(int[] nums) { count = 0; merge(nums, 0, nums.length - 1); return count; } public void merge(int[] nums, int left, int right) { if (left < right) { int mid = left + ((right - left) >> 1); merge(nums, left, mid); merge(nums, mid + 1, right); mergeSort(nums, left, mid, right); } } public void mergeSort(int[] nums, int left, int mid, int right) { int[] temparr = new int[right - left + 1]; int temp1 = left, temp2 = mid + 1, index = 0; //计算翻转对 while (temp1 <= mid && temp2 <= right) { //这里需要防止溢出 if (nums[temp1] > 2 * (long) nums[temp2]) { count += mid - temp1 + 1; temp2++; } else { temp1++; } } //记得归位,我们还要继续使用 temp1 = left; temp2 = mid + 1; //归并排序 while (temp1 <= mid && temp2 <= right) { if (nums[temp1] <= nums[temp2]) { temparr[index++] = nums[temp1++]; } else { temparr[index++] = nums[temp2++]; } } //照旧 if (temp1 <= mid) System.arraycopy(nums, temp1, temparr, index, mid - temp1 + 1); if (temp2 <= right) System.arraycopy(nums, temp2, temparr, index, right - temp2 + 1); System.arraycopy(temparr, 0, nums, left, right - left + 1); } } ``` Python Code: ```python from typing import List class Solution: count = 0 def reversePairs(self, nums: List[int])->int: self.count = 0 self.merge(nums, 0, len(nums) - 1) return self.count def merge(self, nums: List[int], left: int, right: int): if left < right: mid = left + ((right - left) >> 1) self.merge(nums, left, mid) self.merge(nums, mid + 1, right) self.mergeSort(nums, left, mid, right) def mergeSort(self, nums: List[int], left: int, mid: int, right: int): temparr = [0] * (right - left + 1) temp1 = left temp2 = mid + 1 index = 0 while temp1 <= mid and temp2 <= right: # 这里需要防止溢出 if nums[temp1] > 2 * nums[temp2]: self.count += mid - temp1 + 1 temp2 += 1 else: temp1 += 1 # 记得归位,我们还要继续使用 temp1 = left temp2 = mid + 1 # 归并排序 while temp1 <= mid and temp2 <= right: if nums[temp1] <= nums[temp2]: temparr[index] = nums[temp1] index += 1 temp1 += 1 else: temparr[index] = nums[temp2] index += 1 temp2 += 1 # 照旧 if temp1 <= mid: temparr[index: index + mid - temp1 + 1] = nums[temp1: temp1 + mid - temp1 + 1] if temp2 <= right: temparr[index: index + right - temp2 + 1] = nums[temp2: temp2 + right - temp2 + 1] nums[left: left + right- left + 1] = temparr[0: right - left + 1] ```