LeetCode 热题 100 | 堆(二)

目录

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();
    }
};


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】科立讯通信指挥调度平台editemedia.php sql注入漏洞

漏洞描述 在20240318之前的福建科立讯通信指挥调度平台中发现了一个漏洞。该漏洞被归类为关键级别,影响文件/api/client/editemedia.php的未知部分。通过操纵参数number/enterprise_uuid可导致SQL注入。攻击可能会远程发起。 免责声明 技术文章仅供参考,任何个人和组织使…

2024公认口碑最好的洗地机有哪些?若看重清洁力,这四款最值得买

每当我们要清洁卫生时&#xff0c;是否总是感到腰酸背痛、疲劳不堪&#xff0c;甚至头昏眼花&#xff1f;地板是家中的重要门面&#xff0c;不容忽视的卫生焦点。如今&#xff0c;我们终于多了一位家务打扫的救星——家用洗地地机。一次操作&#xff0c;即可完成扫地除尘、地除…

Git 分布式版本控制系统基本概念和操作命令

目录 Git 基本概念 功能特点 工作流程 操作命令 新建代码库 配置 增删文件 代码提交 分支 标签 查看信息 远程同步 撤销 其他 小结 Git Git 是一个开源的分布式版本控制系统&#xff0c;用于跟踪文件的变更历史。它最初由 Linux Torvalds 设计&#xff0c;用于…

1+x中级题目练习复盘(八)

SQL 语句中进行 group by 分组时&#xff0c;可以不写 where 子句 在使用 select 语句进行查询分组时&#xff0c;如果希望去掉不满足条件的分组&#xff0c;使用 having 子句File 类的 isDirectory() 方法可以判断文件是否为目录 在使用 select 语句进行查询分组时&#xff0…

二.寄存器

1. 2. 例如&#xff1a;h即为high&#xff08;高位&#xff09;&#xff0c;l即为low&#xff08;低位&#xff09; 3.一个字是两个字节 4.在写一条汇编指令或一个寄存器的名称时不区分大小写。 5.al&#xff0c;ah&#xff0c;ax在接受汇编指令时&#xff0c;并不相等&…

33-Java服务定位器模式 (Service Locator Pattern)

Java服务定位器模式 实现范例 服务定位器模式&#xff08;Service Locator Pattern&#xff09;用于想使用 JNDI 查询定位各种服务的时候考虑到为某个服务查找 JNDI 的代价很高&#xff0c;服务定位器模式充分利用了缓存技术在首次请求某个服务时&#xff0c;服务定位器在 JNDI…

十三、MySQL基于GTID的半同步复制

目录 一、MySQL半同步复制 一、三种复制方式比较 1、异步复制 2、同步复制 3、半同步复制 4、半同步复制比较 5、半同步复制的特点 二、搭建半同步复制 1、如果不清楚Plugin的目录&#xff0c;用如下查找&#xff1a; 2、所有数据库服务器&#xff0c;安装半同步插件…

【Go实现】实践GoF的23种设计模式:解释器模式

上一篇&#xff1a;【Go实现】实践GoF的23种设计模式&#xff1a;适配器模式 简单的分布式应用系统&#xff08;示例代码工程&#xff09;&#xff1a;https://github.com/ruanrunxue/Practice-Design-Pattern–Go-Implementation 简介 解释器模式&#xff08;Interpreter Pat…

【STM32嵌入式系统设计与开发】——6矩阵按键应用(4x4)

这里写目录标题 一、任务描述二、任务实施1、SingleKey工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;LED IO初始化函数(LED_Init())&#xff08;3&#xff09;开发板矩阵键盘IO初始化&#xff08;ExpKeyBordInit()&#xff09;&…

JVM本地方法

本地方法接口 NAtive Method就是一个java调用非java代码的接口 本地方法栈&#xff08;Native Method Statck&#xff09; Java虚拟机栈用于管理Java方法的调用&#xff0c;而本地方法栈用于管理本地方法的调用。 本地方法栈&#xff0c;也是线程私有的。 允许被实现成固定或…

Matlab|基于分布式ADMM算法的考虑碳排放交易的电力系统优化调度研究

目录 1 主要内容 目标函数 计算步骤 节点系统 2 部分代码 3 程序结果 4 下载链接 1 主要内容 程序完全复现文献《A Distributed Dual Consensus ADMM Based on Partition for DC-DOPF with Carbon Emission Trading》&#xff0c;建立了一个考虑碳排放交易的最优模型&am…

【测试开发学习历程】MySQL分组查询与子查询 + MySQL表的联结操作

目录 1 MySQL分组查询与子查询 1.1 数据分组查询 1.2 过滤分组 1.3 分组结果排序 1.4 select语句中子句的执行顺序 1.5 子查询 2 MySQL表的联结操作 2.1 关系表 2.2 表联结 2.3 笛卡尔积 2.4 内部联结 2.5 外联结 2.6 自联结 2.7 组合查询 1 MySQL分组查询与子查询…

Java学习路线一条龙

说在前面 讲真&#xff0c;虽然我是正规计算机专业出身&#xff0c;但十多年来&#xff0c;Java这语言和它那一大堆配套的工具、框架&#xff0c;变化得太快了。 我也是一边学新的&#xff0c;一边扔旧的&#xff0c;忙得不可开交。 现在回想起来&#xff0c;走过的弯路、浪费…

2024年【危险化学品经营单位安全管理人员】新版试题及危险化学品经营单位安全管理人员模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员新版试题考前必练&#xff01;安全生产模拟考试一点通每个月更新危险化学品经营单位安全管理人员模拟考试题题目及答案&#xff01;多做几遍&#xff0c;其实通过危险化学品经营单位安…

C++默认构造函数(二)

目录 构造函数补充 构造函数初始化列表的使用 赋值运算符重载函数 运算符重载函数介绍 运算符重载函数的使用 赋值运算符重载函数 赋值运算符重载函数的使用 拷贝构造函数和赋值运算符重载函数 重载前置和后置 前置 后置 重载流插入<<与流提取>> 流插…

ngrok实现内网穿透

在使用jenkins进行自动化部署时&#xff0c;需要设置github的webhook钩子来触发构建&#xff0c;由于jenkins运行在自己的电脑上&#xff0c;因此需要通过内网穿透来接受http请求。 Install ngrok via Homebrew with the following command: brew install ngrok/ngrok/ngrokP…

微信小程序开发学习笔记——4.2showModal和showLoading界面交互操作

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 课程连接&#xff1a;https://www.bilibili.com/video/BV19G4y1K74d?p27&vd_source9b149469177ab5fdc47515e14cf3cf74 一、showModal 显示模态对话框 1、属性 https:/…

电商爬虫系统|电商数据采集|电商API商品数据采集

1、基本的说明 当初为了在几个电商网站抓取商品信息数据搭建的系统。该系统主要用来抓取电商网站上面的一百个左右品类的商品的价格信息、商品信息和折扣信息等。抓取的电商网站主要是某宝和某东。其他的电商网站抓取信息的方式无外乎这两种。跟其他的示例代码不同&#xff0c…

【redis】服务器架构演进

架构演进 单机架构应用数据分离架构应⽤服务集群架构读写分离 / 主从分离架构冷热分离架构垂直分库微服务架构 单机架构 所有的应用服务、业务所需的数据、业务处理等都在一台服务器上。 在初期&#xff0c;用户访问量很少&#xff0c;对服务器的的性能和安全没有很高的要求&am…

抖音视频无水印批量下载软件|爬虫视频采集工具

抖音视频无水印批量下载软件&#xff0c;轻松实现视频提取和下载 概述&#xff1a; 想要快速、方便地提取和下载抖音视频无水印&#xff1f;我们的抖音视频无水印批量下载软件将是您的得力助手&#xff01;不仅支持通过关键词批量提取视频&#xff0c;还可以针对特定视频进行提…