深度剖析优先级队列:堆的搭建至解题策略全方位解读

深度解析优先级队列:堆的构建到解题策略的全面解读

在这里插入图片描述

算法 相关知识点 可点击 以下链接学习 共同进步!
双指针
滑动窗口
二分查找
前缀和
位运算
模拟
链表
哈希表
字符串模拟
栈模拟(非单调栈)

优先级队列(Priority Queue),其本质是支持动态插入与按优先级弹出操作的堆结构,是解决这类问题的高效工具。本文将从底层堆的实现出发,逐步构建优先级队列的完整解题框架,并结合高频题目,助你掌握其在算法实战中的应用。

请添加图片描述

Alt

文章目录

  • 一、铺垫知识
    • 1.1 堆排序(Heap Sort)
    • 1.2 快速选择(QuickSelect)算法解Top K问题
    • 3.Tok问题中,大根堆与小根堆的使用场景
    • 1046. 最后一块石头的重量
    • 703. 数据流中的第K大元素
    • 692. 前K个高频单词
    • 295. 数据流的中位数

本专题借助优先级队列解决问题。首先需了解堆与快速选择算法解Top K问题,明确大根堆与小根堆的适用场景及选择依据。

在这里插入图片描述

一、铺垫知识

1.1 堆排序(Heap Sort)

堆排序利用最大堆(Max Heap)或最小堆(Min Heap)实现排序。

可参考文章:理解堆的特性与应用

1.2 快速选择(QuickSelect)算法解Top K问题

用选择排序解Top K(Tok)问题时,无需全排序,仅需K次选择找第K大(小)元素
将上述步骤整合
快速选择排序整合
若用选择排序解Top K问题,仅需K次选择过程找第K大(或K小)元素。

3.Tok问题中大根堆与小根堆的场景

  • 大根堆(Max Heap):
  • 用于取最大元素或Top K 最小元素(维护K个最小元素,堆顶最大)。
  • 示例:找 前K小(维护大小为K的大根堆)。
  • 小根堆(Min Heap):
  • 用于取最小元素或Top K 最大元素(维护K个最大元素,堆顶最小)。
  • 示例:找 前K大(维护大小为K的小根堆)

1046. 最后一块石头的重量

【题目】:1046. 最后一块石头的重量

在这里插入图片描述

【算法思路】

利用堆的特性,反复取出当前最大两值碰撞,将结果插回堆。

【代码实现】

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        int n = stones.size();
        priority_queue<int> pq;
        for (auto x : stones) pq.push(x);
        while (pq.size() > 1) {
            int x = pq.top(); pq.pop();
            int y = pq.top(); pq.pop();
            if (x > y) pq.push(x - y);
        }
        return pq.size() ? pq.top() : 0;
    }
};

703. 数据流中的第K大元素

【题目】:703. 数据流中的第K大元素

在这里插入图片描述

【算法思路】

此题为Top K问题,用小根堆。插入新元素时,若堆大小超K,移除堆顶(最小)。插入时,堆自动调整,堆顶为K大元素中最小。若插入元素大于堆顶,替换;否则不变。动态维护第K大。

【代码实现】

class KthLargest {
public:
    priority_queue<int, vector<int>, greater<int>> pq;
    int k;
    KthLargest(int k, vector<int>& nums) {
        this->k = k;
        for (auto x : nums) {
            pq.push(x);
            if (pq.size() > k) pq.pop();
        }
    }

    int add(int val) {
        pq.push(val);
        if (pq.size() > k) pq.pop();
        return pq.top();
    }
};

692. 前K个高频单词

【题目】:692. 前K个高频单词

在这里插入图片描述

【算法思路】

本题用堆解Top K,需选堆结构。有两排序:频次用小根堆,保证堆顶是K个中频次最低;字典序(频次同)用大根堆,保证同频次降序。因字典序是频次子集,比较函数中加if实现多条件。结果倒序,用小根堆维护前K高频。

【代码实现】

class Solution {
public:
    using PSI = pair<string, int>;
    struct Cmp {
        bool operator()(const PSI& a, const PSI& b) {
            if (a.second == b.second) {
                return a.first < b.first;
            }
            return a.second > b.second;
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string, int> cnt;
        for (auto& str : words) cnt[str]++;
        priority_queue<PSI, vector<PSI>, Cmp> pq;
        for (auto& p : cnt) {
            pq.push(p);
            if (pq.size() > k) pq.pop();
        }
        vector<string> res(k);
        for (int i = k - 1; i >= 0; i--) {
            res[i] = pq.top().first;
            pq.pop();
        }
        return res;
    }
};

295. 数据流的中位数

【题目】:295. 数据流的中位数

在这里插入图片描述

【算法思路】

数据量大时前两法可能超时,用大小堆维护。根据m==n和m>n(m=n+1)分类,num<x放大根堆,否则放小根堆。调整维护。

【代码实现】

class MedianFinder {
public:
    priority_queue<int> left; // 大根堆
    priority_queue<int, vector<int>, greater<int>> right; // 小根堆

    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;
        } else {
            return left.top();
        }
    }
};

【细节】

访问left.top()前检查堆非空,如条件left.empty() || num <= left.top()。

在这里插入图片描述
快来和小二开启算法之旅!关注我,一同破解算法难题,探索实用有趣知识,开启编程冒险!

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12972.html

赞 (0)
LomuLomu
上一篇 2025 年 7 月 25 日
下一篇 2025 年 7 月 25 日

相关推荐

  • 最新PyCharm激活码,新版本PyCharm激活码(win和mac都可以用)

    最新PyCharm激活码,新版本PyCharm激活码(win和mac都可以用) 本教程适用于IDEA、PyCharm、DataGrip、Goland等,支持Jetbrains全家桶! 不多赘述,先上最新PyCharm版本破解成功的截图,如下图所示,可以看到已经成功破解到 2099 年辣,舒服! 接下来,接下来我会用图加文字, 来详细讲解如何激活 PyChar…

    PyCharm破解教程 2025 年 4 月 10 日
    99100
  • 2026国内ChatGPT Plus充值开通攻略

    近年想在国内开通ChatGPT Plus,最大的难题从来不是要不要开,而是怎么完成支付。不少用户走到付款环节才发现,国内银行卡、地区限制、支付环境层层卡壳,折腾半天还是开通失败。本文整理了目前国内四种主流的ChatGPT Plus充值开通方法,讲清楚每种方法的适配人群、操作步骤和优缺点,帮你少走弯路。 方法一:代充网站(目前最省心推荐) PS:省事省时间,是…

    ChatGPT 2026 年 4 月 6 日
    47500
  • 2026年最新 PyCharm 破解方式,亲测有效

    PyCharm2025.2.1破解教程:永久激活码+补丁下载(图文详解) 重要提示:本文所涉及的PyCharm破解补丁及激活码均来源于网络收集,仅限于个人学习研究使用,严禁用于商业用途。如有侵犯版权,请及时联系作者删除。经济条件允许的话,强烈建议支持正版软件! 话不多说,先奉上PyCharm 2025.2.1版本破解成功的实拍图,如下图所示,可以看到激活有效…

    PyCharm激活码 2026 年 4 月 12 日
    1.3K00
  • IDEA破解工具推荐,轻松搞定2025激活!

    免责声明:下文所涉 IntelliJ IDEA 破解补丁、激活码均收集自互联网,仅供个人学习研究,禁止商用。若条件允许,请支持正版! IntelliJ IDEA 是 JetBrains 打造的一款跨平台 IDE,支持 Windows、macOS 与 Linux。下面手把手教你用破解补丁把 IDEA 解锁到 2099 年,畅享全部高级特性。 无论你当前系统或版…

    IDEA破解教程 2025 年 9 月 23 日
    83400
  • ChatGPT Plus订阅还是Pro订阅?同一周里既有例行任务又总有加急插队的人,这样选更稳

    同一周里既有例行任务,又会突然插入紧急需求时,很多人都会重新考虑 ChatGPT Plus订阅 和 ChatGPT Pro订阅 怎么选。真正影响判断的,不是表面上的月费差,而是你这一周的工作节奏:平时是否按清单推进,临时是否经常要赶汇报、救改稿、补数据解释。如果大部分时间是稳定执行,Plus 往往够用;如果一周里总有几次必须立刻出结果,Pro 更像给高峰时段…

    ChatGPT 2026 年 4 月 14 日
    39800

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信