Skip to content

Commit 547126e

Browse files
committed
Create quick_select.md
1 parent fc79da7 commit 547126e

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

advanced_algorithm/quick_select.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# 快速选择
2+
3+
## 使用场景
4+
5+
- 最大/最小的K个数
6+
- 最大/最小的第K个数
7+
8+
## 算法思路
9+
10+
和快速排序的思路类似,但是不需要得出精确的比较顺序。首先从数组中随机或指定挑选一个元素作为标志,然后将所有比这个标志小的元素放在左边,比标志大的放在右边,最后会有以下三种可能的情况:
11+
12+
1. 这个位置就是K,直接返回即可
13+
2. 这个位置小于K,说明K位置的数在右边
14+
3. 这个位置大于K,说明K位置的数在左边
15+
16+
## 算法实现
17+
18+
> [215. 数组中的第K个最大元素](https://leetcode-cn.com/problems/kth-largest-element-in-an-array/)
19+
>
20+
>在未排序的数组中找到第 **k** 个最大的元素。请注意,需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
21+
22+
```java
23+
public int findKthLargest(int[] nums, int k) {
24+
int l = 0;
25+
int r = nums.length - 1;
26+
while (l < r) {
27+
// 对标志两边分别进行处理
28+
int pivot = partition(nums, l, r);
29+
// 标志就是k
30+
if (pivot == nums.length - k) {
31+
break;
32+
}
33+
// k位置在标志的右侧
34+
else if (pivot < nums.length - k) {
35+
l = pivot + 1;
36+
}
37+
// k位置在标志的左侧
38+
else {
39+
r = pivot - 1;
40+
}
41+
}
42+
return nums[nums.length - k];
43+
}
44+
45+
private int partition(int[] nums, int start, int end) {
46+
int l = start;
47+
int r = end + 1;
48+
// 选择首元素作为比较标志
49+
// 比标志小的放在左边,比标志大的放在右边
50+
while (true) {
51+
while (nums[++l] < nums[start] && l < end);
52+
while (nums[--r] > nums[start] && r > start);
53+
if (l >= r) {
54+
break;
55+
}
56+
swap(nums, l, r);
57+
}
58+
// 将标志交换到中间
59+
swap(nums, start, r);
60+
return r;
61+
}
62+
63+
private void swap(int[] nums, int i, int j) {
64+
int temp = nums[i];
65+
nums[i] = nums[j];
66+
nums[j] = temp;
67+
}
68+
```
69+
70+
71+

0 commit comments

Comments
 (0)