【數據結構】c++優先隊列priority_queue及應用

概述

c++ STL中的優先隊列與普通隊列相似,需要頭文件#include <queue>
優先隊列可以看成進行按優先級排列的隊列,它本質是一個堆實現的。
優先隊列的定義形式爲:
priority_queue<Type, Container, Functional>

舉例:

//大頂
priority_queue <int,vector<int>,less<int> >q;   //less<int>可以省略,默認大頂
//小頂
priority_queue <int,vector<int>,greater<int> > q;

優先隊列與普通隊列具有相似的操作,如:

top 訪問隊頭元素
empty 隊列是否爲空
size 返回隊列內元素個數
push 插入元素到隊尾
pop 彈出隊頭元素

應用

leetcode題215:數組中的第K個最大元素

在未排序的數組中找到第 k 個最大的元素。請注意,你需要找的是數組排序後的第 k 個最大的元素,而不是第 k 個不同的元素。

示例 1:

輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例 2:

輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4
說明:

你可以假設 k 總是有效的,且 1 ≤ k ≤ 數組的長度。

解答

思路:
// 1 使用堆,可以使用優先隊列 priority_queue來存放數據
// 2 維護優先隊列(大頂堆)的大小爲 k ,堆頂就是第 k 個最大的數
// 3 注意:當堆的大小已經是 k 個的時候,需要注意直接與堆頂判斷決定是否加入堆中,這樣效率高

// 作者:ikaruga
// 鏈接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/215-by-ikaruga/
// 來源:力扣(LeetCode)
// 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k)
    {
        priority_queue<int, vector<int>, greater<int>> pq;//加greater表示是小頂堆

        for (auto& n : nums){
            //若堆中已有k個元素,且當前元素小於棧頂,則直接跳過
            if (pq.size() >= k && pq.top() >= n) 
                continue;

            pq.push(n);
            if (pq.size() > k){ //維持k個元素
                pq.pop();
            }
        }
        return pq.top();
    }
};

leetcode題347 前k個高頻元素

示例 1:
輸入: nums = [1,1,1,2,2,3], k = 2
輸出: [1,2]

示例 2:
輸入: nums = [1], k = 1
輸出: [1]

提示:

你可以假設給定的 k 總是合理的,且 1 ≤ k ≤ 數組中不相同的元素的個數。
你的算法的時間複雜度必須優於 O(n log n) , n 是數組的大小。
題目數據保證答案唯一,換句話說,數組中前 k 個高頻元素的集合是唯一的。
你可以按任意順序返回答案。
————————————————————————————————————
解答:
與上一題相似,主要區別在於這裏的優先隊列要存儲vector< pair<int,int> >,且要按頻率排列。

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> record;  //(元素,頻率)
        //遍歷數組,錄入頻率
        for(int i = 0; i < nums.size(); i++){
            record[nums[i]]++;
        }
        int n = record.size();

        //掃描record。維護當前出現頻率最多的k個元素
        //最小堆。如果當前元素的頻率大於優先隊列中最小頻率元素的頻率,則替換
        //優先隊列中,按頻率排序,所以數據對是(頻率,元素)形式
        priority_queue< pair<int,int> , vector< pair<int,int> >, greater< pair<int,int> > > pq;
        for(auto iter = record.begin(); iter != record.end(); iter++){
            if(k == pq.size()){ //隊列已滿
                if(iter->second > pq.top().first){
                    pq.pop();
                    pq.push(make_pair(iter->second,iter->first));
                }
            }
            else{
                pq.push(make_pair(iter->second,iter->first));
            }
        }

        vector<int> result;
        while(!pq.empty()){
            result.push_back(pq.top().second);
            pq.pop();
        }

        //更正
        reverse(result.begin(), result.end());

        return result;
    }
};

// 作者:breadhunter
// 鏈接:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/c-xiao-gen-dui-qiu-qian-kda-by-zhengguanyu/
// 來源:力扣(LeetCode)
// 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章