LeetCode 热题 100 | 堆(二)

news2024/9/27 12:11:44

目录

1  什么是优先队列

1.1  优先队列与堆的关系

1.2  如何定义优先队列

1.3  如何使用优先队列

1.4  如何设置排序规则

2  347. 前 K 个高频元素

2.1  第 2 步的具体实现

2.2  举例说明

2.3  完整代码

3  215. 数组中的第 K 个最大元素 - v2


菜鸟做题,语言是 C++

1  什么是优先队列

1.1  优先队列与堆的关系

优先队列:它是一种抽象数据类型,可以看作是一个队列或栈的变体,元素按照优先级的高低排列。在 C++ 中,优先队列通常使用堆来实现。

个人理解,优先队列是对堆的底层原理的封装,谁不用谁是傻子 (bushi)

1.2  如何定义优先队列

参考博客:c++ 优先队列(priority_queue)用法详解

定义如下:

priority_queue<Type, Container, Functional>

① Type 是指数据类型,即你要装什么类型的数据。

② Container 是指容器类型,即你用什么样的容器装数据。

Container 必须是用数组实现的容器,比如:vector、deque等等,不能用 list 。STL 里面默认用的是 vector 。

③ Functional 是指比较的方式,即你希望数据之间以什么样的规则来排序。

只有当数据类型比较复杂的时候才需要设置 Functional,比如你的数据是个键值对。针对基本的数据类型,不需要设置 Functional,默认是大根堆(即谁大谁排前面)。

举例说明

假设我要让优先队列装 int 型的数据,那么就有:

priority_queue<int, vector<int>> q;

如果我不想使用默认的大根堆排序方法,则有:

priority_queue<int, vector<int>, decltype(& cmp)> q(cmp);

其中 cmp 是你自定义的排序函数,返回值是 bool 类型。

如果我想让优先队列装键值对类型的数据,则有:

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(& cmp)> q(cmp);

不过就是把数据类型换了,基本结构都是一样的。

1.3  如何使用优先队列
  • q.push(data) 插入元素
  • q.pop() 弹出队首元素
  • q.top() 获取队首元素
  • q.size() 获取队列大小
  • q.empty() 判断是否为空

以上就是优先队列的基本操作,可以看出它和栈、队列的操作是一样的,无痛学习。

1.4  如何设置排序规则

假设我要为键值对排序,因此对队列定义如下:

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(& cmp)> q(cmp);

其中,pair<int, int> 的第一个 int 是键,第二个 int 是值。要求 cmp 是一个函数指针(即函数的地址),decltype 是类型推导。

排序规则如下:

static bool cmp(pair<int, int> m, pair<int, int> n) {
    return m.second > n.second;
}

其中,m.second 和 n.second 分别代表键值对 m 和 n 的值。

Q:为什么要加 static?

A:因为不加会报错:

  • “error: must explicitly qualify name of member function when taking its address”
  • “错误:在取成员函数的地址时必须显式限定成员函数的名称”

为什么是 m.second > n.second?这样看起来不是谁的值更大,谁排前面吗?答:我也不知道啊。

2  347. 前 K 个高频元素

好不容易通过  215. 数组中的第 K 个最大元素  学会了堆排序,准备大展身手,结果运行超时。。

解题思路:

  1. 遍历 nums 并使用 hash 为其中的所有数字计数
  2. 遍历 hash 并使用 priority_queue 为其中的计数结果排序

2.1  第 2 步的具体实现

① 定义优先队列:

priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(& cmp)> q(cmp);

为什么存储的数据类型是 pair<int, int>?因为我们要同时存储 “数字” 和它的 “个数”,否则后面把 “个数” 的顺序排出来了,却不知道这些 “个数” 对应的 “数字” 是哪些。

② 遍历 hash 并使用 priority_queue 为其中的计数结果排序:

  • 依次向 priority_queue 插入数据,但限制 priority_queue 的大小最终为 k
  • 若当前元素的 count 比队首元素的 count 大,那么弹出队首,换当前元素进去
for (auto & [num, count] : hash) {
    if (q.size() < k) {
        q.push(make_pair(num, count));
    } else if (q.size() == k) {
        if (count > q.top().second) {
            q.pop();
            q.push(make_pair(num, count));
        }
    }
}

2.2  举例说明

这里用字母只是为了方便区分,原题还是用的数字

  • 假设 nums = [a, b, b, c, c, c], k = 2
  • 易得 hash = [(a, 1), (b, 2), (c, 3)]

下面来看 priority_queue 是怎么操作的:

第 1 时刻,队列大小显然没有到达 k,因此直接插入键值对。第 2 时刻,队列大小显然也没有到达 k,因此直接插入键值对。第 3 时刻,由于席位已满,因此必须判断谁更配进入队列。由于 a 的个数被 c 的个数少,因此 a 被弹出队列为 c 让位。

注意:每当有新元素进入队列的时候,队列都会按照之前设置的排序规则 cmp 为元素重新排队。

2.3  完整代码
class Solution {
public:
    // 排序规则
    static bool cmp(pair<int, int> m, pair<int, int> n) {
        return m.second > n.second;
    }

    vector<int> topKFrequent(vector<int>& nums, int k) {
        // 计数
        unordered_map<int, int> hash;
        for (auto & n : nums) {
            hash[n]++;
        }

        // 排序
        priority_queue<pair<int, int>, vector<pair<int, int>>,
                       decltype(& cmp)> q(cmp);
        for (auto & [num, count] : hash) {
            if (q.size() < k) {
                q.push(make_pair(num, count));
            } else if (q.size() == k) {
                if (count > q.top().second) {
                    q.pop();
                    q.push(make_pair(num, count));
                }
            }
        }

        // 处理结果
        vector<int> ans;
        while (!q.empty()) {
            ans.push_back(q.top().first);
            q.pop();
        }

        return ans;
    }
};

3  215. 数组中的第 K 个最大元素 - v2

模仿  347. 前 K 个高频元素  即可

class Solution {
public:
    static bool cmp(int a, int b) {
        return a > b;
    }

    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int, vector<int>, decltype(& cmp)> q(cmp);

        for (auto & n : nums) {
            if (q.size() < k) {
                q.push(n);
            } else if (q.size() == k) {
                if (n > q.top()) {
                    q.pop();
                    q.push(n);
                }
            }
        }

        return q.top();
    }
};


当你有了优先队列,谁还看堆排 (〃>皿<)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1538887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cesium Clock JulianDate 日照分析

cesium在初始化的时候会自动把Clock对象挂载到容器上Clock内部以JulianDate维护时间&#xff0c;比北京时间慢8个小时&#xff0c;想显示北京时间需要计算时差JulianDate的日期部分和秒数部分是分开的 julianDayNumber&#xff1a;指整数天&#xff0c;记录从公元前4713年正午以…

基于SpringBoot实现WebSocket实时通讯的服务端和客户端

实现功能 服务端注册的客户端的列表&#xff1b;服务端向客户端发送广播消息&#xff1b;服务端向指定客户端发送消息&#xff1b;服务端向多个客户端发送消息&#xff1b;客户端给服务端发送消息&#xff1b; 效果&#xff1a; 环境 jdk&#xff1a;1.8 SpringBoot&#x…

社区热议!54.8k Star开源项目,GPT-4Free : 让GPT4免费不是梦

Hello&#xff0c;我是Aitrainee&#xff0c;GPT4Free就是最近传得沸沸扬扬的那个GPT4项目。大家都知道&#xff0c;虽然ChatGPT是免费的&#xff0c;但如果你想用到那些功能更强大的大模型&#xff0c;比如GPT-4、gemini-pro、claude&#xff0c;那就只能选择付费了。 但现在&…

在Linux搭建Emlog博客结合内网穿透实现公网访问本地个人网站

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总结 前言 博客作为使…

【2024最新版,redis7】redis底层的10种数据结构

前言&#xff1a;本文redis版本&#xff1a;7.2.4 本文语雀原文地址&#xff08;首发更新&#xff09;&#xff1a;https://www.yuque.com/wzzz/redis/xg2cp37kx1s4726y 本文CSDN转载地址&#xff1a; https://blog.csdn.net/u013625306/article/details/136842107 1. 常见的数…

烯冷新能源邀您参观2024长三角快递物流展

参加企业介绍 宁波戈雷贝拓科技有限公司&#xff08;宁波烯冷新能源科技有限公司&#xff09;宁波烯冷新能源科技有限公司于2022年初成立&#xff0c;依托中国科学院宁波材料技术与工程研究所和国家石墨烯创新中心&#xff0c;公司开发产品包括&#xff1a;新能源制冷系统和集…

Mysql学习--深入探究索引和事务的重点要点与考点

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

一键入门Ubuntu22!

目录 一、安装 二、常用目录 三、常用指令 四、用户指令 五、ssh与scp 六、服务相关 七、Python与Pycharm 八、Vim编辑器 九、Ubuntu22下使用Mysql 十、Ubuntu22下使用mongodb 十一、Ubuntu22下使用redis Ubuntu是一个基于Debian的开源操作系统&#xff0c;由Canoni…

LeetCode每日一题——x 的平方根

x 的平方根OJ链接&#xff1a;69. x 的平方根 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 思路&#xff1a; 乍一看题目只需要算一个数的平方根&#xff0c;根据我们之前学的C语言我们能很快的想到使用sqrt&#xff0c;pow这类的<math.h>库函数&#xf…

【计算机网络篇】数据链路层(2)封装成帧和透明传输

文章目录 &#x1f95a;封装成帧和透明传输&#x1f388;封装成帧&#x1f388;透明传输&#x1f5d2;️面向字节的物理链路使用字节填充的方法实现透明传输。&#x1f5d2;️面向比特的物理链路使用比特填充的方法实现透明传输。 &#x1f6f8;练习 &#x1f95a;封装成帧和透…

【目标检测基础篇】目标检测评价指标:mAP计算的超详细举例分析以及coco数据集标准详解(AP/AP50/APsmall.....))

学习视频&#xff1a; 霹雳吧啦Wz-目标检测mAP计算以及coco评价标准 【目标检测】指标介绍&#xff1a;mAP 1 TP/FP/FN TP(True Positive) : IoU>0.5的检测框数量(同一Ground truth只计算一次)FP(False Positive) : IoU<0.5的检测框(或者是检测到同一个GT的多余检测框的…

(css)vue 自定义背景 can‘t resolve

(css)vue 自定义背景 can’t resolve 旧写法&#xff1a; background-image: url(/assets/images/step-bg.jpg);background-size: 100% 100%; 新写法&#xff1a; background-image: url(~/assets/images/step-bg.jpg);background-size: 100% 100%; 解决参考&#xff1a;https…

印刷企业实施MES管理系统如何做好需求分析

在数字化、信息化的大潮中&#xff0c;印刷企业面临着转型升级的迫切需求。MES管理系统作为连接企业资源计划ERP和现场自动化系统的桥梁&#xff0c;对于提升印刷企业的生产效率、优化资源配置、提高产品质量具有重要意义。因此&#xff0c;做好MES管理系统的需求分析&#xff…

分布式搜索引擎elasticsearch专栏二

上一篇的传送门&#xff1a; 分布式搜索引擎elasticsearch专栏一-CSDN博客 这一篇博文主要讲解elasticsearch的数据搜索功能。下面会分别使用DSL和RestClient实现搜索。 1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsea…

基于ssm的勤工助学管理系统+数据库+报告+免费远程调试

项目介绍: 基于ssm的勤工助学管理系统。Javaee项目&#xff0c;ssm项目。采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc Mybatisplus VuelayuiMaven来实现。有管理员和老…

​酒店小程序开发的功能与优势解析

随着科技的快速发展和移动互联网的普及&#xff0c;越来越多的服务行业开始尝试利用小程序来提供便捷的服务。对于酒店业来说&#xff0c;开发一个酒店小程序不仅可以提升用户体验&#xff0c;还有助于提高运营效率。本文将详细介绍酒店小程序的开发功能以及它的优势。 一、酒…

Echarts 利用多X轴实现未来15天天气预报

Echarts 利用多X轴实现未来15天天气预报 UI 设计图 Echarts 实现效果 代码实现 代码分解 echarts 图表上下均显示数据 通过设置 grid.top 和 grid.bottom 设置白天和夜间天气展示区域 grid: {top: 36%,bottom: 36%,left: 5%,right: 5%}, 天气图标的设置 由于 axisLabel 的…

Redis中AOF、RDB和复制功能对过期键的处理

AOF、RDB和复制功能对过期键的处理 生成RDB文件 在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时&#xff0c;程序会对数据库中的键进行检查&#xff0c;已过期的键不会被保存到新创建的RDB文件中。 例子 举个例子&#xff0c;如果数据库中包含三个键k1、k2、k3&#x…

六种GPU虚拟化:除了直通、全虚拟化 (vGPU)还有谁?

在大类上计算虚拟化技术有这3种&#xff1a; 软件模拟、直通独占(如网卡独占、显卡独占)、直通共享&#xff08;如vCPU 、vGPU&#xff09;。但对于显卡GPU而言我总结细化出至少这6种分类&#xff1a; 第一种、软件模拟&#xff08;eg sGPU&#xff09;, 又叫半虚拟化。第二种…

活用 C语言之union的精妙之用

一、union的基本定义 Union的中文叫法又被称为共用体、联合或者联合体。它的定义方式与结构体相同,但意义却与结构体完全不同。下面是union的定义格式: union 共用体名 {成员列表}共用体变量名;它与结构体的定义方式相同,但区别在于共用体中的成员的起始地址都是相同的,…