Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法
Java中優(yōu)先隊(duì)列PriorityQueue的使用
簡(jiǎn)單使用
PriorityQueue<Integer> p = new PriorityQueue<>();
優(yōu)先級(jí)隊(duì)列從隊(duì)頭取元素,從隊(duì)尾添加元素。
默認(rèn)情況下,隊(duì)列中的數(shù)據(jù)是升序排序。
PriorityQueue<Integer> p = new PriorityQueue<>();
p.offer(5);
p.offer(1);
p.offer(3);
p.offer(6);
p.offer(8);
while(!p.isEmpty()) {
System.out.println(p.poll());
}運(yùn)行結(jié)果:
1
3
5
6
8
方法
和隊(duì)列的方法基本一樣

自定義排序規(guī)則
以下代碼改變排序規(guī)則,從大到?。?/p>
PriorityQueue<Integer> queue=new PriorityQueue<>((o1,o2)->o2-o1); PriorityQueue<Integer> queue= new PriorityQueue<>(Comparator.reverseOrder());
根據(jù)HashMap的value值對(duì)HashMap的鍵值對(duì)排序
public static void main(String[] args) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(1, 2);
map.put(3, 4);
map.put(5, 6);
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();//獲取鍵值對(duì)
//自定義優(yōu)先隊(duì)列的排序規(guī)則,隊(duì)列內(nèi)存放的數(shù)據(jù)類型是鍵值對(duì)
//o1,o2都是鍵值對(duì)這樣的對(duì)象
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> {
return o1.getValue() - o2.getValue();//根據(jù)值升序排序
});
for (Map.Entry<Integer, Integer> entry : entries) {
queue.offer(entry);//將鍵值對(duì)放到優(yōu)先隊(duì)列中
}
while(!queue.isEmpty()) {
System.out.println(queue.poll().getValue());
}
}運(yùn)行結(jié)果:
2
4
6
優(yōu)先隊(duì)列PriorityQueue (大根堆/小根堆/TopK問題)
PriorityQueue是從JDK1.5開始提供的新的數(shù)據(jù)結(jié)構(gòu)接口,它是一種基于優(yōu)先級(jí)堆的極大優(yōu)先級(jí)隊(duì)列。優(yōu)先級(jí)隊(duì)列是不同于先進(jìn)先出隊(duì)列的另一種隊(duì)列。每次從隊(duì)列中取出的是具有最高優(yōu)先權(quán)的元素。
默認(rèn)情況下,PriorityQueue是小頂堆,如代碼所示
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
queue.offer(5);
queue.offer(6);
while (!queue.isEmpty()){
System.out.print(queue.poll() + " ");
}
}輸出結(jié)果:

我們也可以通過以下方式來構(gòu)造大頂堆:
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>((o1,o2) -> o2 - o1);//降序
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
queue.offer(5);
queue.offer(6);
while (!queue.isEmpty()){
System.out.print(queue.poll() + " ");
}
}輸出結(jié)果:

Top K問題,力扣347和力扣692:
力扣347:給你一個(gè)整數(shù)數(shù)組 nums 和一個(gè)整數(shù) k ,請(qǐng)你返回其中出現(xiàn)頻率前 k 高的元素。你可以按 任意順序 返回答案。
示例:
輸入: nums = [1,1,1,2,2,3], k = 2
輸出: [1,2]
代碼如下:注意構(gòu)造小頂堆的時(shí)候(o1,o2)-> o1.getValue() - o2.getValue() 不能省略。
public int[] topKFrequent(int[] nums, int k) {
//key為元素值,value為出現(xiàn)頻率
HashMap<Integer,Integer> map = new HashMap<>();
PriorityQueue<Map.Entry<Integer, Integer>> queue
= new PriorityQueue<>((o1,o2)-> o1.getValue() - o2.getValue());
int[] res = new int[k];
for (int num : nums) {
map.put(num,map.getOrDefault(num,0) + 1);
}
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
for (Map.Entry<Integer, Integer> entry : entries) {
queue.offer(entry);
if(queue.size() > k){
queue.poll();
}
}
//留下的都是出現(xiàn)頻率最高的
for(int i = 0; i < k; i++){
Map.Entry<Integer, Integer> poll = queue.poll();
res[i] = poll.getKey();
}
return res;力扣692:給定一個(gè)單詞列表 words 和一個(gè)整數(shù) k ,返回前 k 個(gè)出現(xiàn)次數(shù)最多的單詞。返回的答案應(yīng)該按單詞出現(xiàn)頻率由高到低排序。如果不同的單詞有相同出現(xiàn)頻率, 按字典順序排序。
示例:
輸入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
輸出: ["i", "love"]
解析: "i" 和 "love" 為出現(xiàn)次數(shù)最多的兩個(gè)單詞,均為2次。注意,按字母順序 "i" 在 "love" 之前。
這題比上題難一點(diǎn),因?yàn)楫?dāng)兩個(gè)單詞出現(xiàn)次數(shù)一致時(shí)還要考慮按字典序排序,其次是答案需要從高到底排序,這里主要體現(xiàn)在優(yōu)先隊(duì)列PriorityQueue的構(gòu)造上。
代碼如下:
public List<String> topKFrequent(String[] words, int k) {
List<String> res = new ArrayList<>();
//key為元素,value為出現(xiàn)頻率
HashMap<String,Integer> map = new HashMap<>();
for (String word : words) {
map.put(word,map.getOrDefault(word,0) + 1);
}
PriorityQueue<Map.Entry<String,Integer>> queue = new PriorityQueue<>(
((o1, o2) -> {
if(o1.getValue() == o2.getValue()){
return o2.getKey().compareTo(o1.getKey());
}
return o1.getValue() - o2.getValue();
})
);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
queue.offer(entry);
if(queue.size() > k){
queue.poll();
}
}
for(int i = 0; i < k; i++){
res.add(queue.poll().getKey());
}
Collections.reverse(res);
return res;
}注意o2.getKey().compareTo(o1.getKey())是按字典倒序,為什么要這么做呢,是因?yàn)槲覀冞@里用到小頂堆,所以每次poll出來的都是最小頻率元素,最后需要reverse一下,為了配合這個(gè),所以我們構(gòu)造優(yōu)先隊(duì)列的時(shí)候采用字典倒序。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
@RequestBody,@RequestParam和@Param的區(qū)別說明
這篇文章主要介紹了@RequestBody,@RequestParam和@Param的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java實(shí)現(xiàn)的圖片高質(zhì)量縮放類定義與用法示例
這篇文章主要介紹了Java實(shí)現(xiàn)的圖片高質(zhì)量縮放類定義與用法,涉及java針對(duì)圖片的運(yùn)算與轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
Java深入學(xué)習(xí)圖形用戶界面GUI之創(chuàng)建窗體
圖形編程中,窗口是一個(gè)重要的概念,窗口其實(shí)是一個(gè)矩形框,應(yīng)用程序可以使用其從而達(dá)到輸出結(jié)果和接受用戶輸入的效果,學(xué)習(xí)了GUI就讓我們用它來創(chuàng)建一個(gè)窗體2022-05-05
SpringBoot基于MyBatis-Plus實(shí)現(xiàn)Lambda Query查詢的示例代碼
MyBatis-Plus 是 MyBatis 的增強(qiáng)工具,簡(jiǎn)化了數(shù)據(jù)庫操作,并提高了開發(fā)效率,它提供了多種查詢方式,包括常規(guī)的 SQL 查詢、Lambda Query 查詢、分頁查詢、條件查詢等,在本篇博客中,我們將詳細(xì)講解如何使用 MyBatis-Plus 的各種查詢方式,需要的朋友可以參考下2025-01-01
spring boot中多線程開發(fā)的注意事項(xiàng)總結(jié)
spring boot 通過任務(wù)執(zhí)行器 taskexecutor 來實(shí)現(xiàn)多線程和并發(fā)編程。下面這篇文章主要給大家介紹了關(guān)于spring boot中多線程開發(fā)的注意事項(xiàng),文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09
SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringMVC自定義參數(shù)綁定實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11

