-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathFindKthLargest.java
More file actions
103 lines (94 loc) · 3.29 KB
/
FindKthLargest.java
File metadata and controls
103 lines (94 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package com.haobin.leetcode.arrays;
import java.util.Arrays;
import java.util.PriorityQueue;
/**
* @Author HaoBin
* @Create 2020/2/7 12:38
* @Description: 寻找第K个最大元素
* <p>
* 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
* <p>
* 示例 1:
* <p>
* 输入: [3,2,1,5,6,4] 和 k = 2
* 输出: 5
* 示例 2:
* <p>
* 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
* 输出: 4
* 说明:
* <p>
* 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
**/
public class FindKthLargest {
/**
* 暴力解法, 排序后取倒数第K个
*/
public int findKthLargest1(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - 1 - k];
}
/**
* 优先队列
* 因为第 K 大元素,其实就是整个数组排序以后后半部分最小的那个元素。因此,我们可以维护一个有 K 个元素的最小堆:
* 1. 如果当前堆不满,直接添加
* 2. 堆满的时候,如果新读到的数小于等于堆顶,肯定不是我们要找的元素,只有新都到的数大于堆顶的时候,
* 才将堆顶拿出,然后放入新读到的数,进而让堆自己去调整内部结构
* <p>
* <p>
* 思路1:把 len 个元素都放入一个最小堆中,然后再 pop() 出 len - k 个元素,此时最小堆只剩下 k 个元素,堆顶元素就是数组中的第 k 个最大元素。
* <p>
* 思路2:把 len 个元素都放入一个最大堆中,然后再 pop() 出 k - 1 个元素,因为前 k - 1 大的元素都被弹出了,此时最大堆的堆顶元素就是数组中的第 k 个最大元素。
*/
public int findKthLargest2(int[] nums, int k) {
int len = nums.length;
PriorityQueue<Integer> minHeap = new PriorityQueue<>(len, (a, b) -> {
return a - b;
});
for (int i = 0; i < len; i++) {
minHeap.add(nums[i]);
}
for (int i = 0; i < len - k; i++) {
minHeap.poll();
}
return minHeap.peek();
}
/**
* 快排思想
* 找到快排的基准点, 如果刚好是第k个元素, 那么返回这个元素对应的值
* @param nums
* @param k
* @return
*/
public int findKthLargest(int[] nums, int k) {
return findK(nums, 0, nums.length-1, k);
}
public int findK(int[] arr, int left, int right, int k) {
if (left <= right) {
int pivot = partition(arr, left, right);
if (pivot == k - 1) {
return arr[pivot];
} else if (pivot < k - 1) {
return findK(arr, pivot + 1, right, k);
} else {
return findK(arr, left, pivot - 1, k);
}
}
return -1;
}
public int partition(int[] arr, int left, int right) {
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] <= pivot) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] >= pivot) {
left++;
}
arr[right] = arr[left];
}
arr[left] = pivot;
return left;
}
}