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

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

在这里插入图片描述

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

优先级队列(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 日

相关推荐

  • 新版 Cursor 把其他 AI 编程工具按在地上摩擦了!

    大家好,我是汤师爷~ AI编程助手Cursor背后的Anysphere公司刚刚完成了1亿美元的B轮融资,估值直接飙升至26亿美元。 四个月前,这家公司刚拿下6000万美元,估值还只有4亿美元。如今,增长6.5倍,这速度,简直让人怀疑开挂了。 Anysphere不仅融资拿到手软,收入增长更是逆天。 公司从4月的年收入400万美元,短短六个月后,10月的月收入竟…

    2025 年 1 月 15 日
    47200
  • 2025年最新PyCharm激活码与永久破解教程(支持2099年)

    本方法适用于JetBrains全家桶,包括PyCharm、IDEA、DataGrip、Goland等所有产品! 先给大家看看最新PyCharm版本成功破解的截图,可以看到已经完美激活到2099年,非常稳定! 下面我将通过详细的图文教程,手把手教你如何将PyCharm永久激活至2099年。 这个方法不仅适用于最新版本,之前的旧版本也同样有效! 兼容所有操作系统…

    PyCharm激活码 2025 年 8 月 18 日
    29500
  • IDEA破解从入门到精通|实用技巧全公开!

    申明:本教程 IntelliJ IDEA 破解补丁、激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除。若条件允许,希望大家购买正版 ! IDEA是 JetBrains 推出的开发编辑器,功能强大,适用于 Windows、Mac 和 Linux 系统。本文将详细介绍如何通过破解补丁实现永久激活,解锁所有高级功能。 不管你是什么版本、什么…

    2025 年 9 月 29 日
    5400
  • 2025年最新PyCharm激活码与永久破解教程(支持2099年)

    本方法适用于JetBrains全家桶,包括PyCharm、IDEA、DataGrip、Goland等开发工具! 先给大家展示最新PyCharm版本成功破解的截图,可以看到已经完美激活至2099年,完全无压力! 下面我将用详细的图文教程,手把手教你如何将PyCharm永久激活至2099年。 这个方法不仅适用于最新版本,对旧版本也同样有效! Windows/Ma…

    PyCharm激活码 2025 年 8 月 16 日
    20600
  • GoLand激活工具脚本大全|适合自动化部署!

    申明:本教程 GoLand破解补丁、激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除。若条件允许,希望大家购买正版 ! GoLand是 JetBrains 推出的开发编辑器,功能强大,适用于 Windows、Mac 和 Linux 系统。本文将详细介绍如何通过破解补丁实现永久激活,解锁所有高级功能。 不管你是什么版本、什么操作系统。都…

    2025 年 9 月 30 日
    5500

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信