Skip to content

Commit b88256f

Browse files
author
lucifer
committed
1 parent bbf0abf commit b88256f

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
255255
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
256256
- [0301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
257257
- [0460.lfu-cache](./problems/460.lfu-cache.md) 🆕
258+
- [0493.reverse-pairs](./problems/493.reverse-pairs.md) 🆕
258259
- [1168.optimize-water-distribution-in-a-village](./problems/1168.optimize-water-distribution-in-a-village-cn.md) 🆕
259260

260261
### 数据结构与算法的总结

problems/493.reverse-pairs.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
## 题目地址(493. 翻转对)
2+
3+
https://leetcode-cn.com/problems/reverse-pairs/description/
4+
5+
## 题目描述
6+
7+
```
8+
给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。
9+
10+
你需要返回给定数组中的重要翻转对的数量。
11+
12+
示例 1:
13+
14+
输入: [1,3,2,3,1]
15+
输出: 2
16+
示例 2:
17+
18+
输入: [2,4,3,5,1]
19+
输出: 3
20+
注意:
21+
22+
给定数组的长度不会超过50000。
23+
输入数组中的所有数字都在32位整数的表示范围内。
24+
25+
```
26+
27+
## 暴力法
28+
29+
### 思路
30+
31+
读完这道题你应该就能联想到逆序数才行。求解逆序数最简单的做法是使用双层循环暴力求解。我们仿照求解决逆序数的解法来解这道题(其实唯一的区别就是系数从 1 变成了 2)。
32+
33+
### 代码
34+
35+
代码支持:Python3
36+
37+
Python3 Code:
38+
39+
```python
40+
class Solution(object):
41+
def reversePairs(self, nums):
42+
n = len(nums)
43+
cnt = 0
44+
for i in range(n):
45+
for j in range(i + 1, n):
46+
if nums[i] > 2 * nums[j]:
47+
cnt += 1
48+
return cnt
49+
```
50+
51+
## 分治法
52+
53+
### 思路
54+
55+
如果你能够想到逆序数,那么你很可能直到使用类似归并排序的方法可以求解逆序数。实际上逆序数只是归并排序的副产物而已。
56+
57+
我们在正常的归并排序的代码中去计算逆序数即可。由于每次分治的过程,左右两段数组分别是有序的,因此我们可以减少一些运算。 从时间复杂度的角度上讲,我们从$O(N^2)$优化到了 $O(NlogN)$。
58+
59+
具体来说,对两段有序的数组,有序数组内部是不需要计算逆序数的。 我们计算逆序数的逻辑只是计算两个数组之间的逆序数,我们假设两个数组是 A 和 B,并且 A 数组最大的元素不大于 B 数组最小的元素。而要做到这样,我们只需要常规的归并排序即可。
60+
61+
接下来问题转化为求解两个有序数组之间的逆序数,并且两个有序数组之间满足关系`A数组最大的元素不大于B数组最小的元素`
62+
63+
关于计算逆序数的核心代码(Python3):
64+
65+
```python
66+
l = r = 0
67+
while l < len(left) and r < len(right):
68+
if left[l] <= 2 * right[r]:
69+
l += 1
70+
else:
71+
self.cnt += len(left) - l
72+
r += 1
73+
```
74+
75+
### 代码
76+
77+
代码支持:Python3
78+
79+
Python3 Code:
80+
81+
```python
82+
class Solution(object):
83+
def reversePairs(self, nums):
84+
self.cnt = 0
85+
86+
def mergeSort(lst):
87+
L = len(lst)
88+
if L <= 1:
89+
return lst
90+
return mergeTwo(mergeSort(lst[:L//2]), mergeSort(lst[L//2:]))
91+
92+
def mergeTwo(left, right):
93+
l = r = 0
94+
while l < len(left) and r < len(right):
95+
if left[l] <= 2 * right[r]:
96+
l += 1
97+
else:
98+
self.cnt += len(left) - l
99+
r += 1
100+
return sorted(left+right)
101+
102+
mergeSort(nums)
103+
return self.cnt
104+
105+
```
106+
107+
对于具体的排序过程我们偷懒直接使用了语言内置的方法 sorted,这在很多时候是有用的,即使你是参加面试,这种方式通常也是允许的。省略非核心的考点,可以使得问题更加聚焦,这是一种解决问题的思路,在工作中也很有用。
108+
109+
## 关键点解析
110+
111+
- 归并排序
112+
- 逆序数
113+
- 分治
114+
- 识别考点,其他非重点可以使用语言内置方法
115+
116+
## 代码
117+
118+
## 扩展
119+
120+
这道题还有很多别的解法,感性的可以参考下这个题解 [General principles behind problems similar to "Reverse Pairs"](https://leetcode.com/problems/reverse-pairs/discuss/97268/General-principles-behind-problems-similar-to-%22Reverse-Pairs%22)

0 commit comments

Comments
 (0)