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

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

在这里插入图片描述

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

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

相关推荐

  • Mysql身份认证过程

    背景 最近有一些hersql的用户希望能支持mysql的caching_sha2_password认证方式,caching_sha2_password与常用的mysql_native_password认证过程差异还是比较大的,因此抽空研究了一下caching_sha2_password身份认证过程,并为hersql支持了caching_sha2_passwo…

    2025 年 1 月 14 日
    29600
  • python SQLAlchemy ORM——从零开始学习 04 如何过滤(筛选)数据库中的数据

    04 如何过滤(筛选)数据库中的数据 从数据库中获筛选数据主要应用以下几个接口:filter、filter_by、以及 where。前两个在 02已经展开说过,先展开说where接口 前情提要:依赖03提及的model【本质上就是数据库的链接,有可忽视】 当前的数据库表内容如下,仅作例子,不相同根据自身数据库操作即可: 4-1 通过where进行筛选 同时筛…

    2025 年 1 月 15 日
    45700
  • 最新PyCharm激活教程 – 如何进行永久破解与激活

    本教程适用于PyCharm 2025、IDEA、DataGrip、Goland等Jetbrains产品,支持全家桶激活!无论您使用的是Windows、Mac还是Linux,均可按照本教程成功激活PyCharm 2025至2098年。 激活截图展示 首先,我们来展示一下最新版本的PyCharm 2025破解成功的截图,如下所示,您可以看到已经成功激活至2098…

    PyCharm破解教程 2025 年 4 月 23 日
    1.5K00
  • PyCharm破解教程,激活码分享,适用于Windows和Mac系统

    本教程适用于PyCharm、PyCharm、DataGrip、Goland等,支持Jetbrains全家桶! 废话不多说,先给大家看一下最新PyCharm版本的破解截图,可以看到已经成功破解至2099年,激活效果非常好! 接下来,我会通过图文方式,详细讲解如何激活PyCharm至2099年。 无论你使用的是Windows、Mac还是Linux系统,无论你的P…

    2025 年 4 月 12 日
    55500
  • 2025年最新PyCharm激活码及永久破解教程(支持2099年)

    JetBrains系列工具(如IDEA、PyCharm、DataGrip、Goland等)的破解方法其实非常简单!先看最新PyCharm版本成功破解到2099年的效果图: 本教程将详细介绍如何永久激活PyCharm至2099年,该方法同样适用于旧版本,无论你是Windows、Mac还是Linux系统,都能100%成功激活! 下载PyCharm安装包 已安装用…

    2025 年 5 月 8 日
    29300

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信