堆的OJ题

       🔥🔥 欢迎来到小林的博客!!
      🛰️博客主页:✈️林 子
      🛰️博客专栏:✈️ 小林的算法笔记
      🛰️社区 :✈️ 进步学堂
      🛰️欢迎关注:👍点赞🙌收藏✍️留言

目录

  • 703. 数据流中的第 K 大元素
  • 692. 前K个高频单词
  • 295. 数据流的中位数

703. 数据流中的第 K 大元素

题目链接:703. 数据流中的第 K 大元素

题目描述:

设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

请实现 KthLargest 类:

  • KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
  • int add(int val)val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

示例:

输入:
["KthLargest", "add", "add", "add", "add", "add"]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
输出:
[null, 4, 5, 5, 8, 8]解释:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3);   // return 4
kthLargest.add(5);   // return 5
kthLargest.add(10);  // return 5
kthLargest.add(9);   // return 8
kthLargest.add(4);   // return 8

提示:

  • 1 <= k <= 104
  • 0 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • -104 <= val <= 104
  • 最多调用 add 方法 104
  • 题目数据保证,在查找第 k 大元素时,数组中至少有 k 个元素

解题思路: 这一题是典型的topK问题,第K大我们可以建小堆。第K小我们可以建大堆。为什么要这样呢?因为建小堆的话,我们的堆顶就是最小的。我Top一个后,新的堆顶就是倒数第二小的。当我们的堆只有的元素只有K个的时候。那么堆顶的元素就是 nums.size - k小的。反过来就是第K大的。nums这里指的是整个数组。

假设整个数组的大小为 7 , k 为6。 那么当堆的大小为6时,堆顶的元素就是 nums.size - 1(nums.size - heap.size)。也就是第6大的数。所以,TOPK问题找第K大建小堆,找第K小建大堆,我们要反着来。虽然正着来也可以解决单纯的topK问题,但是这一题是有add操作的,如果正着来。那么前面pop掉最大的数据就丢失了。而最小的数据却没有关系,因为小堆存的是最大的K个数。堆顶是最大K个数中最小的一个。

在这里插入图片描述

所以这一题我们可以建一个小堆。然后把nums所有的数push进去,最后再把堆pop到K的大小。而每次add就push一次,再pop一次,即可维持堆的大小为K。

代码:

class KthLargest {
public:priority_queue<int,vector<int>,greater<int>> _min_heap;int _k;KthLargest(int k, vector<int>& nums) {_k = k ;for(auto& n : nums)_min_heap.push(n); while(_min_heap.size() > k) _min_heap.pop();}int add(int val) {_min_heap.push(val);if(_min_heap.size() > _k) _min_heap.pop();return _min_heap.top();}
};

运行结果:

在这里插入图片描述

692. 前K个高频单词

题目链接: 692. 前K个高频单词

题目描述:

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

示例 1:

输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。注意,按字母顺序 "i" 在 "love" 之前。

示例 2:

输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,出现次数依次为 4, 3, 2 和 1 次。

注意:

  • 1 <= words.length <= 500
  • 1 <= words[i] <= 10
  • words[i] 由小写英文字母组成。
  • k 的取值范围是 [1, **不同** words[i] 的数量]

**进阶:**尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。

解题思路:

首先这一题有2个关键点,第一点是按频次比较。第二点是频次相同时,按字母序排序。所以这里我们要一个哈希表来统治所有字符串出现的次数。然后再把哈希表的这一对key,value值入堆,而堆的大小也和上题一样设置为K个。因为频次取前K个,所以我们对频次用小根堆排。但是频次相同的字符串又要按字母序排,所以对字母序排序我们又要用大堆。

比如第一个用例。我们用堆排好序是这样的。频次用小根堆排,而频次相同,我们则按大根堆对string排。

在这里插入图片描述

而因为我们的K为2,所以堆的大小只能是2。最后变成这样。

在这里插入图片描述

而此时我TOP得到的是字母序较大的值,所以我们在把堆的值填入返回的string数组时需要倒着填,因为小的要放在前面。

要实现这种排序,我们需要自己写一个cmp函数,作为priority_queue的第三个模板参数。

代码:

class Solution {typedef pair<string,int> PSI; //排序的仿函数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; //小根堆排,大的放下面}};public:vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> map; //1.统计所有字符出现次数for(auto& word : words) map[word]++; //2.将哈希表所有元素入堆priority_queue<PSI,vector<PSI>,cmp> heap; for(auto& it : map) heap.push({it.first,it.second}); //堆的大小只能为k while(heap.size() > k) heap.pop(); //将堆的元素逆序放到ret数组中vector<string> ret(k); for(int i = k - 1; i >= 0 ; i--){//将堆顶字符串放在数组的尾部,逆序放ret[i] = heap.top().first;heap.pop();}return ret;}
};

运行结果:

在这里插入图片描述

295. 数据流的中位数

题目链接:[295. 数据流的中位数

题目描述:

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

  • 例如 arr = [2,3,4] 的中位数是 3
  • 例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5

实现 MedianFinder 类:

  • MedianFinder() 初始化 MedianFinder 对象。
  • void addNum(int num) 将数据流中的整数 num 添加到数据结构中。
  • double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

示例 1:

输入
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
输出
[null, null, null, 1.5, null, 2.0]解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1);    // arr = [1]
medianFinder.addNum(2);    // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3);    // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0

提示:

  • -105 <= num <= 105
  • 在调用 findMedian 之前,数据结构中至少有一个元素
  • 最多 5 * 104 次调用 addNumfindMedian

解题思路:

题目是找中位数,那么我们可以用2个堆。一个大堆,一个小端。大于中位数的值放小堆里面,小于等于中位数的值放大堆里面。我们只需要保证两个堆的大小相等,或者大堆的大小比小堆大1。每当一次add操作时,我们先判断两个堆大小是否相等。如果相等,则说明要往大堆push数据,那么我们先把num放进小堆,再取小堆的堆顶放入大堆,这样大堆的长度就+1了。如果不相等,说明大堆的大小比小堆大1,那么我们要往小堆push数据,所以我们先把num放进大堆,再取大堆的堆顶放入小堆。

在这里插入图片描述

代码:

class MedianFinder {
public:priority_queue<int,vector<int>,greater<int>> _less_heap;//小堆priority_queue<int,vector<int>,less<int>> _greater_heap;//大堆MedianFinder() {}void addNum(int num) {if(_greater_heap.size() == 0){//第一次插入,直接入大堆_greater_heap.push(num); return; }//其他次插入,判断俩个堆的大小if(_greater_heap.size() == _less_heap.size()){//两个堆的大小相等,则放进大堆,不过需要先把num放进小堆,取小堆的堆顶放入大堆_less_heap.push(num);int top = _less_heap.top();_less_heap.pop();_greater_heap.push(top); }else {//两个堆大小不相等,则说明大堆多一个,把num放进大堆,取大堆的堆顶放入小堆,俩个堆的大小则平衡_greater_heap.push(num); int top = _greater_heap.top();_greater_heap.pop();_less_heap.push(top);}}double findMedian() {//如果俩个堆大小相等,返回堆顶和 /2 ,反之返回大堆堆顶if(_less_heap.size() == _greater_heap.size())return (_less_heap.top() + _greater_heap.top()) / 2.0; return _greater_heap.top();}
};

运行结果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis深度历险 千帆竞发 —— 分布式锁

分布式应用进行逻辑处理时经常会遇到并发问题。 比如一个操作要修改用户的状态&#xff0c;修改状态需要先读出用户的状态&#xff0c;在内存里进行修改&#xff0c;改完了再存回去。如果这样的操作同时进行了&#xff0c;就会出现并发问题&#xff0c;因为读取和保存状态这两个…

生产消费者模型的介绍以及其的模拟实现

目录 生产者消费者模型的概念 生产者消费者模型的特点 基于阻塞队列BlockingQueue的生产者消费者模型 对基于阻塞队列BlockingQueue的生产者消费者模型的模拟实现 ConProd.c文件的整体代码 BlockQueue.h文件的整体代码 对【基于阻塞队列BlockingQueue的生产者消费者模型…

uniapp----微信小程序 日历组件(周日历 月日历)【Vue3+ts+uView】

uniapp----微信小程序 日历组件&#xff08;周日历&& 月日历&#xff09;【Vue3tsuView】 用Vue3tsuView来编写日历组件&#xff1b;存在周日历和月日历两种显示方式&#xff1b;高亮显示当天日期&#xff0c;红点渲染有数据的日期&#xff0c;点击显示数据 1. calenda…

数据结构——AVL树

目录 1.什么是AVL树&#xff1f; 2.AVL树插入的模拟实现 ①节点定义 ②插入 ③旋转 ⑴右单旋 ⑵左单旋 ⑶双旋&#xff08;右左旋&#xff09; ⑷双旋&#xff08;左右旋&#xff09; ⑸完整的插入代码 3.AVL树的性能分析 1.什么是AVL树&#xff1f; AVL树是一种自…

NLP文本生成全解析:从传统方法到预训练完整介绍

目录 1. 引言1.1 文本生成的定义和作用1.2 自然语言处理技术在文本生成领域的使用 2 传统方法 - 基于统计的方法2.1.1 N-gram模型2.1.2 平滑技术 3. 传统方法 - 基于模板的生成3.1 定义与特点3.2 动态模板 4. 神经网络方法 - 长短时记忆网络(LSTM)LSTM的核心概念PyTorch中的LST…

中尺度混凝土二维有限元求解——运行弯曲、运行光盘、运行比较、运行半圆形(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

YOLOv8快速复现 训练 SCB-Dataset3-S 官网版本 ultralytics

目录 0 相关资料SCB-Dataset3-S 数据训练yaml文件 YOLOv8 训练SCB-Dataset3-S相关参数 0 相关资料 YOLOV8环境安装教程.&#xff1a;https://www.bilibili.com/video/BV1dG4y1c7dH/ YOLOV8保姆级教学视频:https://www.bilibili.com/video/BV1qd4y1L7aX/ b站视频&#xff1a;…

ceph分布式存储

ceph特点 Ceph项目最早起源于Sage就读博士期间的工作&#xff08;最早的成果于2004年发表&#xff09;&#xff0c;并随后贡献给开源社区。在经过了数年的发展之后&#xff0c;目前已得到众多云计算厂商的支持并被广泛应用。RedHat及OpenStack都可与Ceph整合以支持虚拟机镜像的…

经典指标策略回测一览

编辑 经典指标策略回测一览 关键词 A股市场&#xff08;沪深京三市&#xff09; 5000股票20年内日线走势回测&#xff0c;区分除权&#xff0c;前复权&#xff0c;后复权三种模式&#xff1b;由于数据量较大&#xff0c;采用两种方式共享数据&#xff0c;一是 天启网站的数据…

每天几道Java面试题:IO流(第五天)

目录 第五幕 、第一场&#xff09;街边 友情提醒 背面试题很枯燥&#xff0c;加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第五幕 、 第一场&#xff09;街边 【衣衫褴褛老者&#xff0c;保洁阿姨&#xff0c;面试者老王】 衣衫褴褛老…

【数据结构】二叉树的·深度优先遍历(前中后序遍历)and·广度优先(层序遍历)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

CDH 集群离线部署、大数据组件安装与扩容详细步骤(cdh-6.3.1)

一、环境准备 1、服务器配置和角色规划 IP 地址主机名硬件配置操作系统安装步骤10.168.168.1cm-server8C16GCentos7新建10.168.168.2agent018C16GCentos7新建10.168.168.3agent028C16GCentos7新建10.168.168.4agent038C16GCentos7新建10.168.168.5agent048C16GCentos7扩容 2…

七天学会C语言-第五天(函数)

1. 调用有参函数 有参函数是一种接受输入参数&#xff08;参数值&#xff09;并执行特定操作的函数。通过向函数传递参数&#xff0c;你可以将数据传递给函数&#xff0c;让函数处理这些数据并返回结果。 例1&#xff1a;编写一程序&#xff0c;要求用户输入4 个数字&#xf…

Innodb底层原理与Mysql日志机制

MySQL内部组件结构 Server层 主要包括连接器、词法分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xff08;如日期、时间、数学和加密函数等&#xff09;&#xff0c;所有跨存储引擎的功能都在这一层实现&#xff0c…

超级详细 SQL 优化大全

1、MySQL的基本架构 1&#xff09;MySQL的基础架构图 左边的client可以看成是客户端&#xff0c;客户端有很多&#xff0c;像我们经常你使用的CMD黑窗口&#xff0c;像我们经常用于学习的WorkBench&#xff0c;像企业经常使用的Navicat工具&#xff0c;它们都是一个客户端。右…

Python实现Redis缓存MySQL数据并支持数据同步

简介 本文讲讲如何用Redis做MySQL的读缓存&#xff0c;提升数据库访问性能。 MySQL是一种很常用的关系型数据库&#xff0c;用于持久化数据&#xff0c;并存放在磁盘上。但如果有大数据量的读写&#xff0c;靠MySQL单点就会捉襟见肘&#xff0c;尽管可以在MySQL本身做优化&am…

Qt httpclient

记录一次Qt中处理https请求的操作 构造函数 get onFinished函数&#xff1a; onCompleted是对外的信号&#xff0c;这里接收的数据主要是文本类 post form post json Form 与 Json的差别是http header 的设置 文件下载处理 这里与服务器有个约定&#xff0c;文件长度不能小于…

springboot整合sentinel完成限流

1、直入正题&#xff0c;下载sentinel的jar包 1.1 直接到Sentinel官网里的releases下即可下载最新版本&#xff0c;Sentinel官方下载地址&#xff0c;直接下载jar包即可。不过慢&#xff0c;可能下载不下来 1.2 可以去gitee去下载jar包 1.3 下载完成后&#xff0c;进行打包…

68、Spring Data JPA 的 方法名关键字查询(全自动,既不需要提供sql语句,也不需要提供方法体)

1、方法名关键字查询&#xff08;全自动&#xff0c;既不需要提供sql语句&#xff0c;也不需要提供方法体&#xff09; 2、Query查询&#xff08;半自动&#xff1a;提供 SQL 或 JPQL 查询&#xff09; 3、自定义查询&#xff08;全手动&#xff09; ★ 方法名关键字查询&…

简明 SQL 组合查询指南:掌握 UNION 实现数据筛选

在SQL中&#xff0c;组合查询是一种将多个SELECT查询结果合并的操作&#xff0c;通常使用UNION和UNION ALL两种方式。 UNION 用于合并多个查询结果集&#xff0c;同时去除重复的行&#xff0c;即只保留一份相同的数据。UNION ALL 也用于合并多个查询结果集&#xff0c;但不去除…