当前位置: 首页 > news >正文

春招百题--堆

一、堆的定义

二、堆(优先队列)

堆通常用于实现优先队列(priority_queue),大顶堆相当于元素按从大到小的顺序出队的优先队列。从使用角度来看,我们可以将“优先队列”和“堆”看作等价的数据结构。

堆的常见用法:

/* 初始化堆 */
// 初始化小顶堆
priority_queue<int, vector<int>, greater<int>> minHeap;
// 初始化大顶堆
priority_queue<int, vector<int>, less<int>> maxHeap;/* 元素入堆 */
maxHeap.push(1);
maxHeap.push(3);
maxHeap.push(2);
maxHeap.push(5);
maxHeap.push(4);/* 获取堆顶元素 */
int peek = maxHeap.top(); // 5/* 堆顶元素出堆 */
// 出堆元素会形成一个从大到小的序列
maxHeap.pop(); // 5
maxHeap.pop(); // 4
maxHeap.pop(); // 3
maxHeap.pop(); // 2
maxHeap.pop(); // 1/* 获取堆大小 */
int size = maxHeap.size();/* 判断堆是否为空 */
bool isEmpty = maxHeap.empty();/* 输入列表并建堆 */
vector<int> input{1, 3, 2, 5, 4};
priority_queue<int, vector<int>, greater<int>> minHeap(input.begin(), input.end());

三、堆的常见应用

  • 优先队列:堆通常作为实现优先队列的首选数据结构,其入队和出队操作的时间复杂度均为 0(log⁡n) ,而建队操作为 0(n),这些操作都非常高效。
  • 堆排序:给定一组数据,我们可以用它们建立一个堆,然后不断地执行元素出堆操作,从而得到有序数据。
  • 获取最大的 K 个元素:这是一个经典的算法问题,同时也是一种典型应用,例如选择热度前 10 的新闻作为微博热搜,选取销量前 10 的商品等。

四、具体思路top-k问题:

  1. 初始化一个小顶堆,其堆顶元素最小。
  2. 先将数组的前 k 个元素依次入堆。
  3. 从第 k+1 个元素开始,若当前元素大于堆顶元素,则将堆顶元素出堆,并将当前元素入堆。
  4. 遍历完成后,堆中保存的就是最大的 k个元素。
/* 基于堆查找数组中最大的 k 个元素 */
priority_queue<int, vector<int>, greater<int>> topKHeap(vector<int> &nums, int k) {// 初始化小顶堆priority_queue<int, vector<int>, greater<int>> heap;// 将数组的前 k 个元素入堆for (int i = 0; i < k; i++) {heap.push(nums[i]);}// 从第 k+1 个元素开始,保持堆的长度为 kfor (int i = k; i < nums.size(); i++) {// 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆if (nums[i] > heap.top()) {heap.pop();heap.push(nums[i]);}}return heap;
}

总共执行了 n 轮入堆和出堆,堆的最大长度为 k ,因此时间复杂度为 0(nlogk)。该方法的效率很高,当 k 较小时,时间复杂度趋向0(n) ;当k 较大时,时间复杂度不会超过 0(nlog⁡n) 。

另外,该方法适用于动态数据流的使用场景。在不断加入数据时,我们可以持续维护堆内的元素,从而实现最大的 k个元素的动态更新

五、习题:

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

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {//建大顶堆priority_queue<int,vector<int>,greater<int>>heap;int n=nums.size();for(int i=0;i<k;i++){heap.push(nums[i]);}for(int i=k;i<n;i++){if(nums[i]>heap.top()){heap.pop();heap.push(nums[i]);}   }return heap.top();}
};

264. 丑数 II

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是质因子只包含 23 和 5 的正整数。

思路:如果x是丑数,则2x、3x、5x也是丑数。所以我们不妨使用一个优先队列,存储这些丑数。

每次取出堆顶元素 x,则 x 是堆中最小的丑数,由于 2x,3x,5x 也是丑数,因此将 2x,3x,5x加入堆。

上述做法会导致堆中出现重复元素的情况。为了避免重复元素,可以使用哈希集合去重,避免相同元素多次加入堆。

哈希去重:

unordered_set<long> seen;//建立哈希表
//seen.count(x)//对x元素计数。if(!seen.count(x))//x此时一个都没有
seen.insert(x);//插入到哈希表中,此时数量就为一了
class Solution {
public:int nthUglyNumber(int n) {//哈希表去重unordered_set<long> seen;vector<int>factors={2,3,5};priority_queue<long,vector<long>,greater<long>>heap;seen.insert(1L);heap.push(1L);int ugly=0;for(int i=0;i<n;i++){long curr=heap.top();heap.pop();ugly=(int)curr;for(int factor:factors){long next=curr*factor;if(!seen.count(next)){seen.insert(next);heap.push(next);}}}return ugly;}
};

另外一个方法:. - 力扣(LeetCode)

http://www.lryc.cn/news/333022.html

相关文章:

  • 全志A40i android7.1 移植wifi驱动的一般流程
  • Qt——Qt绘图之QPainter的使用总结(使用paintEvent实现旋转图片效果)
  • Day83:服务攻防-开发组件安全JacksonFastJson各版本XStreamCVE环境复现
  • 【QT+QGIS跨平台编译】056:【pdal_kazhdan+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
  • 泰坦尼克号幸存者数据分析
  • Memcached 教程之 PHP 连接 Memcached 服务(十)
  • 【zlm】音视频流与音频流合并的设计
  • typescript的工作流
  • MATLAB下载与安装详细教程:从官方获取到成功启动
  • 【随笔】Git 高级篇 -- 分离 HEAD(十一)
  • mac、windows 电脑安装使用多个版本的node
  • vue 浅解watch cli computed props ref vue slot axios nexttick devtools说明使用
  • Unity自定义框架(1)-----------单例模式
  • 04-自媒体文章-自动审核
  • LeetCode-热题100:763. 划分字母区间
  • IDEA2023创建SpringMVC项目
  • ubuntu-server部署hive-part2-安装hadoop
  • Python深度学习032:conda操作虚拟环境env的全部命令
  • 使用Java拓展本地开源大模型的网络搜索问答能力
  • Mybatis——一对多关联映射
  • Pytorch实用教程:TensorDataset和DataLoader的介绍及用法示例
  • uni-app如何实现高性能
  • docker 应用部署
  • java.awt.FontFormatException: java.nio.BufferUnderflowException
  • C++ 枚举类型 ← 关键字 enum
  • MySQL故障排查与优化
  • 如何做一个知识博主? 善用互联网检索
  • 《QT实用小工具·十》本地存储空间大小控件
  • 作为一个初学者该如何学习kali linux?
  • 多线程学习-线程池