优先级队列
# 215. 数组中的第K个最大元素 (opens new window)
方法一:堆
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int num:nums){
pq.offer(num);
if(pq.size()>k){
pq.poll();
}
}
return pq.peek();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
方法二:快排
class Solution {
public int findKthLargest(int[] nums, int k) {
shuffle(nums);
int l=0,r=nums.length-1;
k = nums.length-k;
while(l<=r){
int p = partition(nums,l,r);
if(p<k) l=p+1;
else if(p>k) r=p-1;
else return nums[p];
}
return -1;
}
int partition(int[] nums,int l,int r){
int i = l;
int base = nums[r];
for(int j=l;j<r;j++){
if(nums[j]<base){
swap(nums,i,j);
i++;
}
}
swap(nums,i,r);
return i;
}
void shuffle(int[] nums){
Random random = new Random();
int n = nums.length;
for(int i=0;i<n;i++){
int r = i+random.nextInt(n-i);
swap(nums,i,r);
}
}
void swap(int[] nums,int l,int r){
int tmp = nums[l];
nums[l] = nums[r];
nums[r] = tmp;
}
}
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
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
# 295. 数据流的中位数 (opens new window)
class MedianFinder {
PriorityQueue<Integer> large;
PriorityQueue<Integer> small;
public MedianFinder() {
this.large = new PriorityQueue<>();
this.small = new PriorityQueue<>((a,b)->{
return b-a;
});
}
public void addNum(int num) {
if(large.isEmpty() || num>=large.peek())
large.add(num);
else
small.add(num);
modifyTwoHeapSize();
}
public double findMedian() {
int largeSize = large.size();
int smallSize = small.size();
Integer largeHead = large.peek();
Integer smallHead = small.peek();
if(((largeSize+smallSize)&1)==0)
return (largeHead+smallHead)/2.0;
return largeSize>smallSize?largeHead:smallHead;
}
void modifyTwoHeapSize(){
if(large.size() == small.size()+2)
small.offer(large.poll());
if(small.size() == large.size()+2)
large.offer(small.poll());
}
}
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
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
# 347. 前 K 个高频元素 (opens new window)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<Map.Entry<Integer,Integer>> pq = new PriorityQueue<>((o1,o2)->{
return o1.getValue().compareTo(o2.getValue());
});
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
pq.offer(entry);
if(pq.size()>k){
pq.poll();
}
}
int[] ret = new int[k];
for(int i=k-1;i>=0;i--){
ret[i] = pq.poll().getKey();
}
return ret;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 373. 查找和最小的 K 对数字 (opens new window)
class Solution {
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<List<Integer>> res = new ArrayList<>();
PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->{
return (a[0]+a[1])-(b[0]+b[1]);
});
// 先将a[*]b[0]加入堆
for(int i=0;i<nums1.length;i++){
pq.offer(new int[]{nums1[i],nums2[0],0});
}
while(!pq.isEmpty() && k>0){
int[] cur = pq.poll();
k--;
int idx = cur[2]+1;
if(idx<nums2.length){
pq.add(new int[]{cur[0],nums2[idx],idx});
}
res.add(List.of(cur[0],cur[1]));
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 378. 有序矩阵中第 K 小的元素 (opens new window)
1
# 451. 根据字符出现频率排序 (opens new window)
class Solution {
public String frequencySort(String s) {
Map<Character,Integer> map = new HashMap<>();
for(char c:s.toCharArray()){
map.put(c,map.getOrDefault(c,0)+1);
}
PriorityQueue<Character> pq = new PriorityQueue<>((x,y)->{
return map.get(y)-map.get(x);
});
for(char c:map.keySet()){
pq.offer(c);
}
StringBuilder sb = new StringBuilder();
while(!pq.isEmpty()){
char k = pq.poll();
int v = map.get(k);
while(v-->0){
sb.append((char)k);
}
}
return sb.toString();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 632. 最小区间 (opens new window)
# 659. 分割数组为连续子序列 (opens new window)
class Solution {
public boolean isPossible(int[] nums) {
var map = new HashMap<Integer,PriorityQueue<Integer>>();
for(int x:nums){
if(!map.containsKey(x)){
map.put(x,new PriorityQueue<Integer>());
}
//存在多个子序列以x−1结尾,将x加入其中最短的子序列
if(map.containsKey(x-1)){
int preLen = map.get(x-1).poll();
// 将子序列+1作为x结尾的子序列长度,x-1结尾的子序列减少一个,以x结尾的子序列增加一个
if(map.get(x-1).isEmpty()){
map.remove(x-1);
}
map.get(x).offer(preLen+1);
}else{
map.get(x).offer(1);
}
}
var entrySet = map.entrySet();
for(Map.Entry<Integer,PriorityQueue<Integer>> entry:entrySet){
PriorityQueue<Integer> que = entry.getValue();
if(que.peek()<3){
return false;
}
}
return true;
}
}
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
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