国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

算法沉淀——優(yōu)先級(jí)隊(duì)列(堆)(leetcode真題剖析)

這篇具有很好參考價(jià)值的文章主要介紹了算法沉淀——優(yōu)先級(jí)隊(duì)列(堆)(leetcode真題剖析)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

算法沉淀——優(yōu)先級(jí)隊(duì)列(堆)(leetcode真題剖析),算法沉淀,算法,leetcode,linux


優(yōu)先隊(duì)列(Priority Queue)是一種抽象數(shù)據(jù)類型,它類似于隊(duì)列(Queue),但是每個(gè)元素都有一個(gè)關(guān)聯(lián)的優(yōu)先級(jí)。在優(yōu)先隊(duì)列中,元素按照優(yōu)先級(jí)從高到低(或從低到高)排列,高優(yōu)先級(jí)的元素先出隊(duì)。這種數(shù)據(jù)結(jié)構(gòu)可以用堆(Heap)來實(shí)現(xiàn)。

堆是一種二叉樹結(jié)構(gòu),有兩種主要類型:最大堆和最小堆。在最大堆中,每個(gè)節(jié)點(diǎn)的值都大于或等于其子節(jié)點(diǎn)的值;而在最小堆中,每個(gè)節(jié)點(diǎn)的值都小于或等于其子節(jié)點(diǎn)的值。對(duì)于優(yōu)先隊(duì)列來說,最大堆常常用于實(shí)現(xiàn)。

在堆中,根節(jié)點(diǎn)的元素具有最高(或最低)優(yōu)先級(jí),而且這一性質(zhì)對(duì)于整個(gè)堆中的每個(gè)節(jié)點(diǎn)都成立。這確保了當(dāng)我們從堆中移除元素時(shí),總是移除具有最高(或最低)優(yōu)先級(jí)的元素。

優(yōu)先隊(duì)列的常見操作包括:

  • 插入(Insertion):將元素插入隊(duì)列中。
  • 刪除最大(或最?。┰兀阂瞥⒎祷仃?duì)列中具有最高(或最低)優(yōu)先級(jí)的元素。

堆的實(shí)現(xiàn)可以通過數(shù)組或鏈表等數(shù)據(jù)結(jié)構(gòu)。在使用數(shù)組實(shí)現(xiàn)堆時(shí),父節(jié)點(diǎn)和子節(jié)點(diǎn)之間的關(guān)系可以通過數(shù)組的索引關(guān)系來表示。在C++中,可以使用 std::priority_queue 來實(shí)現(xiàn)優(yōu)先隊(duì)列,它默認(rèn)使用最大堆,也可以通過傳遞自定義比較函數(shù)來實(shí)現(xiàn)最小堆。

01.最后一塊石頭的重量

題目鏈接:https://leetcode.cn/problems/last-stone-weight/

有一堆石頭,每塊石頭的重量都是正整數(shù)。

每一回合,從中選出兩塊 最重的 石頭,然后將它們一起粉碎。假設(shè)石頭的重量分別為 xy,且 x <= y。那么粉碎的可能結(jié)果如下:

  • 如果 x == y,那么兩塊石頭都會(huì)被完全粉碎;
  • 如果 x != y,那么重量為 x 的石頭將會(huì)完全粉碎,而重量為 y 的石頭新重量為 y-x。

最后,最多只會(huì)剩下一塊石頭。返回此石頭的重量。如果沒有石頭剩下,就返回 0。

示例:

輸入:[2,7,4,1,8,1]
輸出:1
解釋:
先選出 7 和 8,得到 1,所以數(shù)組轉(zhuǎn)換為 [2,4,1,1,1],
再選出 2 和 4,得到 2,所以數(shù)組轉(zhuǎn)換為 [2,1,1,1],
接著是 2 和 1,得到 1,所以數(shù)組轉(zhuǎn)換為 [1,1,1],
最后選出 1 和 1,得到 0,最終數(shù)組轉(zhuǎn)換為 [1],這就是最后剩下那塊石頭的重量。 

提示:

  • 1 <= stones.length <= 30
  • 1 <= stones[i] <= 1000

思路

我們可以每次拿出最大的兩個(gè)相比較,有差值就將差值保留,相等就都粉碎,這樣我們很容易想到使用堆去計(jì)算,因?yàn)檫@符合堆的特性,我們可以使用各語言庫中的堆容器來計(jì)算。

  1. 創(chuàng)建最大堆(Max Heap): 通過 priority_queue<int> 創(chuàng)建一個(gè)默認(rèn)為最大堆的優(yōu)先隊(duì)列,將給定的石頭數(shù)組中的元素加入最大堆中。
  2. 迭代處理: 使用一個(gè)循環(huán)迭代處理,直到堆中剩余的元素個(gè)數(shù)小于等于1。
  3. 從堆中取出兩個(gè)最大的元素,執(zhí)行碎石操作: 每次取出堆中的兩個(gè)最大元素(即石頭的重量最大的兩塊),執(zhí)行碎石操作,計(jì)算碎石后的重量,將結(jié)果加回堆中。
  4. 返回結(jié)果: 當(dāng)循環(huán)結(jié)束時(shí),堆中剩余的元素即為最后一塊石頭的重量,或者堆為空,返回相應(yīng)的結(jié)果。

代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-835012.html

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        priority_queue<int> heap;
        for(int x:stones) heap.push(x);

        while(heap.size()>1){
            int a=heap.top(); heap.pop();
            int b=heap.top(); heap.pop();
            if(a>b) heap.push(a-b);
        }

        return heap.size()?heap.top():0;
    }
};

02.數(shù)據(jù)流中的第 K 大元素

題目鏈接:https://leetcode.cn/problems/kth-largest-element-in-a-stream/

設(shè)計(jì)一個(gè)找到數(shù)據(jù)流中第 k 大元素的類(class)。注意是排序后的第 k 大元素,不是第 k 個(gè)不同的元素。

請(qǐng)實(shí)現(xiàn) KthLargest 類:

  • KthLargest(int k, int[] nums) 使用整數(shù) k 和整數(shù)流 nums 初始化對(duì)象。
  • int add(int val)val 插入數(shù)據(jù)流 nums 后,返回當(dāng)前數(shù)據(jù)流中第 k 大的元素。

示例:

輸入:
["KthLargest", "add", "add", "add", "add", "add"]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
輸出:
[null, 4, 5, 5, 8, 8]

解釋:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3);   // return 4
kthLargest.add(5);   // return 5
kthLargest.add(10);  // return 5
kthLargest.add(9);   // return 8
kthLargest.add(4);   // return 8

提示:

  • 1 <= k <= 104
  • 0 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • -104 <= val <= 104
  • 最多調(diào)用 add 方法 104
  • 題目數(shù)據(jù)保證,在查找第 k 大元素時(shí),數(shù)組中至少有 k 個(gè)元素

思路

這里是典型的topk問題,找的是第k個(gè)大的數(shù),所以我們使用一個(gè)k大的小堆就能很好的解決這個(gè)問題。

在構(gòu)造函數(shù)中,將初始的元素加入最小堆中,并維護(hù)堆的大小為 K,保證堆中只有前 K 大的元素。

當(dāng)有新元素加入時(shí),將新元素加入最小堆中,然后檢查堆的大小是否超過 K,如果超過則彈出堆頂元素。最終返回當(dāng)前堆頂元素,即為第 K 大的元素。這樣,通過不斷地將新元素加入最小堆,并保持堆的大小為 K,可以在 add 操作后始終保持堆中的元素為前 K 大的元素,而堆頂元素即為第 K 大的元素。

代碼

class KthLargest {
    priority_queue<int,vector<int>,greater<int>> heap;
    int _k;
public:
    KthLargest(int k, vector<int>& nums) {
        _k=k;
        for(int& x:nums){
            heap.push(x);
            if(heap.size()>k) heap.pop();
        }
    }
    
    int add(int val) {
        heap.push(val);
        if(heap.size()>_k) heap.pop();
        return heap.top();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

03.前K個(gè)高頻單詞

題目鏈接:https://leetcode.cn/problems/top-k-frequent-words/

給定一個(gè)單詞列表 words 和一個(gè)整數(shù) k ,返回前 k 個(gè)出現(xiàn)次數(shù)最多的單詞。

返回的答案應(yīng)該按單詞出現(xiàn)頻率由高到低排序。如果不同的單詞有相同出現(xiàn)頻率, 按字典順序 排序。

示例 1:

輸入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
輸出: ["i", "love"]
解析: "i" 和 "love" 為出現(xiàn)次數(shù)最多的兩個(gè)單詞,均為2次。
    注意,按字母順序 "i" 在 "love" 之前。

示例 2:

輸入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
輸出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出現(xiàn)次數(shù)最多的四個(gè)單詞,
    出現(xiàn)次數(shù)依次為 4, 3, 2 和 1 次。

注意:

  • 1 <= words.length <= 500
  • 1 <= words[i] <= 10
  • words[i] 由小寫英文字母組成。
  • k 的取值范圍是 [1, **不同** words[i] 的數(shù)量]

**進(jìn)階:**嘗試以 O(n log k) 時(shí)間復(fù)雜度和 O(n) 空間復(fù)雜度解決。

思路

很顯然這里這是還是topk問題,還是使用堆來解決問題,但是這里有兩個(gè)比較條件,所以我們要注意比較函數(shù)的實(shí)現(xiàn),主邏輯是找出前k個(gè)出現(xiàn)次數(shù)最多的,所以整體我們建小堆,還有一個(gè)附屬條件,次數(shù)相同時(shí),字典序小的排在前面,所以在相同次數(shù)時(shí),我們相對(duì)于字符串建大堆,將字母小的排在前面。

  1. 哈希表統(tǒng)計(jì)頻率: 使用 unordered_map 哈希表記錄每個(gè)字符串出現(xiàn)的頻率。
  2. 優(yōu)先隊(duì)列: 使用一個(gè)自定義的比較函數(shù)對(duì)象 cmp 作為優(yōu)先隊(duì)列的比較規(guī)則。按照頻率從大到小排序,若頻率相同則按照字符串字典序從小到大排序。遍歷哈希表,將每個(gè)鍵值對(duì)(字符串及其頻率)加入最小堆,并保持堆的大小為 K,當(dāng)堆的大小超過 K 時(shí),彈出堆頂元素。
  3. 結(jié)果處理: 從堆中依次取出前 K 高的字符串,存儲(chǔ)到結(jié)果數(shù)組中。

最終,返回存儲(chǔ)前 K 高字符串的結(jié)果數(shù)組 ret。這樣通過哈希表統(tǒng)計(jì)頻率,并使用優(yōu)先隊(duì)列來維護(hù)前 K 高的頻率,實(shí)現(xiàn)了找出頻率前 K 高的字符串。

代碼

class Solution {
    struct cmp{
        bool operator()(const pair<string,int>& a,const pair<string,int>& b){
            if(a.second==b.second) return a.first<b.first;
            return a.second>b.second;
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string,int> hash;
        for(string& s:words) hash[s]++;

        priority_queue<pair<string,int>,vector<pair<string,int>>,cmp> heap;

        for(const pair<string,int>& x:hash){
            heap.push(x);
            if(heap.size()>k) heap.pop();
        }

        vector<string> ret(k);
        for(int i=k-1;i>=0;--i){
            ret[i]=heap.top().first;
            heap.pop();
        }

        return ret;
    }
};

04.數(shù)據(jù)流的中位數(shù)

題目鏈接:https://leetcode.cn/problems/find-median-from-data-stream/

中位數(shù)是有序整數(shù)列表中的中間值。如果列表的大小是偶數(shù),則沒有中間值,中位數(shù)是兩個(gè)中間值的平均值。

  • 例如 arr = [2,3,4] 的中位數(shù)是 3 。
  • 例如 arr = [2,3] 的中位數(shù)是 (2 + 3) / 2 = 2.5

實(shí)現(xiàn) MedianFinder 類:

  • MedianFinder() 初始化 MedianFinder 對(duì)象。
  • void addNum(int num) 將數(shù)據(jù)流中的整數(shù) num 添加到數(shù)據(jù)結(jié)構(gòu)中。
  • double findMedian() 返回到目前為止所有元素的中位數(shù)。與實(shí)際答案相差 10-5 以內(nèi)的答案將被接受。

示例 1:

輸入
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
輸出
[null, null, null, 1.5, null, 2.0]

解釋
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1);    // arr = [1]
medianFinder.addNum(2);    // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3);    // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

提示:

  • -105 <= num <= 105
  • 在調(diào)用 findMedian 之前,數(shù)據(jù)結(jié)構(gòu)中至少有一個(gè)元素
  • 最多 5 * 104 次調(diào)用 addNumfindMedian

思路

這里我們最容易想到的暴力解法就是每次插入時(shí)排序,但是這種方法時(shí)間復(fù)雜度太高,其實(shí)這里我們可以使用一個(gè)大堆和一個(gè)小堆來維護(hù)所有數(shù),各分一半數(shù)據(jù),若兩邊長度相等,則返回兩個(gè)堆頂相加除2的值,若不等,返回大堆堆頂即可。

在構(gòu)造函數(shù)中初始化兩個(gè)優(yōu)先隊(duì)列,left 用于存放較小的一半元素(最大堆),right 用于存放較大的一半元素(最小堆)。 在 addNum 方法中,根據(jù)元素的大小選擇將其插入到左堆或右堆。插入后需要保持兩個(gè)堆的大小差不超過 1,以確保中位數(shù)的計(jì)算。 在 findMedian 方法中,根據(jù)兩個(gè)堆的大小關(guān)系返回中位數(shù)。通過這種方式,不斷將數(shù)據(jù)插入到兩個(gè)堆中,并保持它們的大小差不超過 1,就能夠在 O(1) 時(shí)間內(nèi)查找到當(dāng)前數(shù)據(jù)流的中位數(shù)。

代碼

class MedianFinder {
    priority_queue<int> left;
    priority_queue<int,vector<int>,greater<int>> right;
public:
    MedianFinder() {}
    
    void addNum(int num) {
        if(left.size()==right.size()){
            if(left.empty()||num<=left.top()) left.push(num);
            else{
                right.push(num);
                left.push(right.top());
                right.pop();
            }
        }
        else{
            if(num<=left.top()){
                left.push(num);
                right.push(left.top());
                left.pop();
            }else right.push(num);
        }
    }
    
    double findMedian() {
        if(left.size()==right.size()) return (left.top()+right.top())/2.0;
        return left.top();
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

到了這里,關(guān)于算法沉淀——優(yōu)先級(jí)隊(duì)列(堆)(leetcode真題剖析)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Linux_進(jìn)程的優(yōu)先級(jí)&&環(huán)境變量&&上下文切換&&優(yōu)先級(jí)隊(duì)列

    Linux_進(jìn)程的優(yōu)先級(jí)&&環(huán)境變量&&上下文切換&&優(yōu)先級(jí)隊(duì)列

    什么是優(yōu)先級(jí)? 指定一個(gè)進(jìn)程獲取某種資源的先后順序 本質(zhì)是進(jìn)程獲取cpu資源的優(yōu)先順序 為什么要有優(yōu)先級(jí) 進(jìn)程訪問的資源(CPU)是有限的 操作系統(tǒng)關(guān)于調(diào)度和優(yōu)先級(jí)的原則:分時(shí)操作系統(tǒng),基本的公平,如果進(jìn)程因?yàn)殚L時(shí)間不被調(diào)整,就造成了饑餓問題 Linux的優(yōu)先級(jí)特

    2024年04月09日
    瀏覽(22)
  • 優(yōu)先級(jí)隊(duì)列【C++】

    優(yōu)先級(jí)隊(duì)列【C++】

    優(yōu)先隊(duì)列(priority_queue)也是隊(duì)列的一種,priority_queue的接口是和queue的接口是相同的。所以兩者的使用語法也是相同的。我們直接看優(yōu)先隊(duì)列(priority——queue)的底層實(shí)現(xiàn)原理。 默認(rèn)情況下priority_queue是大堆。 priority_queue的底層實(shí)際上就是堆,模擬實(shí)現(xiàn)priority_queue之前,需要

    2024年02月10日
    瀏覽(23)
  • 優(yōu)先級(jí)隊(duì)列

    優(yōu)先級(jí)隊(duì)列

    目錄 ?前言: 1、PriorityQueue的特性 .2 PriorityQueue常用接口介紹 Ⅰ、PriorityQueue常見的構(gòu)造方法 ?Ⅱ、常用的方法 Ⅲ、PriorityQueue的擴(kuò)容方式: ?3、應(yīng)用 普通的隊(duì)列是一種 先進(jìn)先出 的數(shù)據(jù)結(jié)構(gòu),元素在隊(duì)列尾追加,而從隊(duì)列頭刪除。在優(yōu)先隊(duì)列中,元素被賦予優(yōu)先級(jí)。當(dāng)訪問元

    2024年02月02日
    瀏覽(28)
  • 【JAVA】優(yōu)先級(jí)隊(duì)列(堆)

    【JAVA】優(yōu)先級(jí)隊(duì)列(堆)

    羨慕別人就讓自己變得更好! 優(yōu)先級(jí)隊(duì)列(堆)可用于topK問題 有大小根堆 注意堆的模擬實(shí)現(xiàn) 堅(jiān)持真的很難但是真的很酷! 隊(duì)列是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),但有些情況下,操作的數(shù)據(jù)可能帶有優(yōu)先級(jí),一般出隊(duì)列時(shí),可能需要優(yōu)先級(jí)高的元素先出隊(duì)列。 此時(shí),數(shù)據(jù)結(jié)

    2024年02月15日
    瀏覽(22)
  • rabbitmq的優(yōu)先級(jí)隊(duì)列

    rabbitmq的優(yōu)先級(jí)隊(duì)列

    在我們系統(tǒng)中有一個(gè) 訂單催付 的場景,我們的客戶在天貓下的訂單 , 淘寶會(huì)及時(shí)將訂單推送給我們,如果在用戶設(shè)定的時(shí)間內(nèi)未付款那么就會(huì)給用戶推送一條短信提醒,很簡單的一個(gè)功能對(duì)吧,但是,tianmao商家對(duì)我們來說,肯定是要分大客戶和小客戶的對(duì)吧,比如像蘋果,

    2024年02月11日
    瀏覽(15)
  • Java優(yōu)先級(jí)隊(duì)列-堆

    大家好,我是曉星航。今天為大家?guī)淼氖?Java優(yōu)先級(jí)隊(duì)列(堆) 的講解!?? 使用數(shù)組保存二叉樹結(jié)構(gòu),方式即將二叉樹用 層序遍歷 方式放入數(shù)組中。 一般只適合表示完全二叉樹,因?yàn)榉峭耆鏄鋾?huì)有空間的浪費(fèi)。 這種方式的主要用法就是堆的表示。 已知雙親(parent)的下

    2023年04月16日
    瀏覽(21)
  • 「數(shù)據(jù)結(jié)構(gòu)」優(yōu)先級(jí)隊(duì)列

    ?? 個(gè)人主頁 :Ice_Sugar_7 ?? 所屬專欄 :Java數(shù)據(jù)結(jié)構(gòu) ?? 歡迎點(diǎn)贊收藏加關(guān)注哦! 優(yōu)先級(jí)隊(duì)列底層是用堆實(shí)現(xiàn)的 ,關(guān)于堆的實(shí)現(xiàn),之前的文章已經(jīng)詳細(xì)介紹過了,文章鏈接:二叉樹1:堆的實(shí)現(xiàn) 方法 功能 PriorityQueue() 創(chuàng)建一個(gè)空的優(yōu)先級(jí)隊(duì)列,默認(rèn)容量是11 PriorityQueue(int i

    2024年02月20日
    瀏覽(46)
  • java 堆(優(yōu)先級(jí)隊(duì)列)詳解

    java 堆(優(yōu)先級(jí)隊(duì)列)詳解

    如果有一個(gè)關(guān)鍵碼的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉樹的順序存儲(chǔ)方式存儲(chǔ) 在一個(gè)一維數(shù)組中,并滿足:Ki = K2i+1 且 Ki= K2i+2 (Ki = K2i+1 且 Ki = K2i+2) i = 0,1,2…,則稱為 小堆(或大堆)。將根節(jié)點(diǎn)最大的堆叫做最大堆或大根堆,根節(jié)點(diǎn)最小的堆叫做最小

    2024年02月08日
    瀏覽(24)
  • RabbitMQ優(yōu)先級(jí)隊(duì)列的使用

    生產(chǎn)者 消費(fèi)者

    2024年02月16日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)】優(yōu)先級(jí)隊(duì)列——堆

    【數(shù)據(jù)結(jié)構(gòu)】優(yōu)先級(jí)隊(duì)列——堆

    ??????????個(gè)人主頁?????????? ??????????數(shù)據(jù)結(jié)構(gòu)專欄?????????? ??????????【數(shù)據(jù)結(jié)構(gòu)】非線性結(jié)構(gòu)——二叉樹?????????? 前面介紹過隊(duì)列,隊(duì)列是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),但有些情況下,操作的數(shù)據(jù)可能帶有優(yōu)先級(jí),一般出隊(duì)列時(shí),可能

    2024年04月14日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包