文章目录
需求:使用优先队列(小根堆或大根堆),解决Top K问题
。
0 优先队列解决Top K问题的原理
小根堆(Min-heap)
:父节点的值小于等于子节点的值;根节点的值最小。
大根堆(Max-heap)
:父节点的值大于等于子节点的值;根节点的值最大。
优先队列
:
优先队列:Java中使用容器
PriorityQueue
表示;C++中使用STL容器priority_queue
表示。
Java优先级队列的原理:
基于优先级堆的极大优先级队列,每次从队列中取出具有最高优先权的元素。
(1)自然排序:默认小根堆、按字典序升序排列
(2)比较器排序:使用lambda表达式
简化比较器。
①小根堆:e1 - e2
;大根堆:e2 - e1
②字典序升序:o1.compareTo(o2)
;字典序降序:o2.compareTo(o1)
0.1 解决Top K大的问题
实现方式:维护大小固定为K的小根堆:比较器排序设置e1 - e2
(小根堆)。
小根堆:小值元素在堆顶,具有最高优先级;大值元素在堆底,具有较低优先级。
①堆大小固定时,插入元素优先更新堆顶的小值元素,以大值元素取代小值元素;
②满足条件后,依次弹出堆顶小值元素并加入结果集,反转结果集即得到Top K大的元素。
补充需求:频度相同时,按字典序(升序)输出
实现方式:比较器排序设置字典序降序即o2.compare(o1)
,即字典序较高的元素在堆顶,具有较高优先级;字典序较低的元素在堆底,具有较低优先级。
①堆大小固定时,插入元素优先更新堆顶的字典序较高元素;
②满足条件时,依次弹出堆顶高字典序元素并加入结果集,反转结果集后即得到低字典序(字典序升序)的元素。
0.2 解决Top K小的问题
实现方式:维护大小固定为K的大根堆:比较器排序设置e2 - e1
(大根堆)。
大根堆:大值元素在堆顶,具有最高优先级;小值元素在堆底,具有较低优先级。
①堆大小固定时,插入元素优先更新堆顶的大值元素,以小值元素取代大值元素;
②满足条件后,依次弹出堆顶大值元素并加入结果集,反转结果集即得到Top K小的元素。
注1:遍历元素的时间复杂度
O(n)
,删除堆顶/弹出堆顶的时间复杂度O(log n)
,获取结果时建议使用删除堆顶的方式。
注2:反转结果集的API:
Java使用Collections.reverse(res);
,需导包import java.util.Collections
。
C++使用reverse(res.begin(), res.end());
,需包含头文件#include <algorithm>
。
1 Java的优先队列PriorityQueue
Java的优先队列,默认创建小根堆/小顶堆/最小堆。
构造方法:
(1)小根堆(默认)
①自然排序(默认升序)
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
②比较器排序(使用lambda表达式
实现)
整型升序:PriorityQueue<Integer> minHeap = new PriorityQueue<>( (i1, i2) -> i1 - i2 );
字典序升序:PriorityQueue<String> minHeap = new PriorityQueue<>( (s1, s2) -> s1.compareTo(s2) );
(2)大根堆
比较器排序(使用lambda表达式
实现)
整型降序:PriorityQueue<Integer> maxHeap = new PriorityQueue<>( (i1, i2) -> i2 - i1 );
字典序降序:PriorityQueue<String> maxHeap = new PriorityQueue<>( (s1, s2) -> s2.compareTo(s1) );
2 C++的优先队列priority_queue
C++的优先队列,默认创建大根堆/大顶堆/最大堆。
模板参数:<class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type>>
第1个参数:元素数据类型(不可省略)
第2个参数:容器类型(可省略)
第3个参数:排序方式(可省略),可传递类类型。
例:泛型类型(指定模板参数类型):priority_queue< type, container, function>;
。
注:priority_queue的第1个参数不可省略,后两个参数可省略,
(1)小根堆
内建函数对象-关系仿函数greater<T>
升序:priority_queue<T, vector<T>, greater<T>> min_heap;
(2)大根堆(默认)
内建函数对象-关系仿函数less<T>
priority_queue<T> max_heap;
priority_queue<T, vector<T>, less<T>> max_heap;