C++ 优先级队列(大小根堆)OJ

目录

1、 1046. 最后一块石头的重量

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

        为什么小根堆可以解决TopK问题? 

3、 692. 前K个高频单词

4、 295. 数据流的中位数


1、 1046. 最后一块石头的重量

 思路:根据示例发现可以用大根堆(降序)模拟这个过程。

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        priority_queue<int> heap;
        for (auto s : stones)
            heap.push(s);
        while (heap.size() > 1) {
            int a = heap.top();
            heap.pop();
            int b = heap.top();
            heap.pop();
            if (a > b)
                heap.push(a - b);
        }
        return heap.size() ? heap.top() : 0;
    }
};

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

 思路:TopK问题使用小根堆堆解决,priority_queue(默认大根堆)的第三个参数为greater<类型>即为小根堆。

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

    int add(int val) {
        heap.push(val);
        if (heap.size() > _k)
            heap.pop();
        return heap.top();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

为什么小根堆可以解决TopK问题? 

对于设计一个找到数据流中第k大元素的类的问题,我们应该使用小根堆(Min Heap)来实现。下面解释为什么使用小根堆以及如何使用它:

  1. 为什么使用小根堆:

    • 小根堆能够保证堆顶元素是堆中最小的元素。在维护数据流中的第k大元素时,我们希望能够快速访问到第k大的元素,而不是最小的元素。通过维护一个大小为k的小根堆,堆中的元素就是数据流中最大的k个元素,而堆顶元素(最小元素)就是这k个元素中第k大的元素。
    • 当新的元素加入时,如果它大于堆顶元素,我们就将它加入堆中,并移除堆顶元素,这样堆的大小仍然保持为k。这样做可以确保堆中始终是数据流中最大的k个元素,而堆顶元素就是这些元素中最小的,即第k大的元素。
  2. 如何使用小根堆:

    • 初始化时,将数组nums中的元素加入小根堆中,如果元素数量超过k,则移除堆顶元素,以保证堆的大小为k。
    • 对于add方法,每次加入一个新元素时,先将其加入到小根堆中。如果加入后堆的大小超过k,则移除堆顶元素。然后返回堆顶元素,即为当前数据流中第k大的元素。

通过使用小根堆,我们可以高效地解决数据流中的第k大元素问题,同时保证时间复杂度和空间复杂度都在合理的范围内。

3、 692. 前K个高频单词

 思路:

  • 频次统计:首先,使用哈希表记录每个单词出现的频次。
  • 优先队列排序:利用优先队列(或小根堆)根据单词的频次和字典序排序,从而找出频次最高的前 k 个单词。

实现步骤

  1. 处理单词列表

    • 利用哈希表统计每个单词出现的次数,确保单词不会重复计数且记录了它们的频次。
  2. 使用小根堆选择前 k 大元素

    • 根据问题要求,设计比较器(cmp):
      • 频次不同:频次较少的优先(小根堆性质)。
      • 频次相同:字典序较小的优先(大根堆性质)。
    • 使用优先队列(小根堆)存储单词及其频次,保证堆的大小不超过 k
    • 将每个单词和它的频次插入到堆中,如果堆的大小超过了 k,就移除堆顶元素。
  3. 获取结果

    • 最终,堆中剩余的就是频次最高的前 k 个单词。反向遍历堆,将元素按正确的顺序存入结果列表中。
class Solution {
public:
    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;
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string,int> hash;
        for(auto& s:words)
            hash[s]++;
        priority_queue<PSI,vector<PSI>,cmp> heap;
        for(auto& psi:hash){
            heap.push(psi);
            if(heap.size()>k)
                heap.pop();
        }
        vector<string> ret(k);
        for(int i=k-1;i>=0;i--){
            ret[i]=heap.top().first;
            heap.pop();
        }
        return ret;
    }
};

4、 295. 数据流的中位数

实现一个动态中位数查找器

 动态数据流中位数查找是一种常见问题,可以通过聪明地运用数据结构来解决。以下是如何通过维护两个堆—一个大根堆和一个小根堆—来实现一个动态中位数查找器的步骤。

解决方法:利用两个堆

算法思路

本解法是一个关于堆数据结构的经典应用。通过将数据流平分或近似平分为两个部分:一个较小部分和一个较大部分—可以高效解决问题:

  • 较小的部分在大根堆(left)中。

  • 较大的部分在小根堆(right)中。

  • 如此设置允许我们在常数时间内获得中位数。

动态添加数据

当有新数据加入时,进行以下步骤以保持两个堆的平衡:

  1. 两个堆的大小相同 (left.size() == right.size()):

    • 若堆为空,直接将 x 放入 left 中。

    • 若 x <= left.top(),将 x 放入 left

    • 否则,先将 x 放入 right,再将 right 的堆顶元素移到 left 中。

  2. 两个堆的大小不相同 (left.size() > right.size()):

    • 若 x 大于或等于 right.top(),直接放入 right

    • 否则,先将 x 放入 left,再将 left 的堆顶元素移到 right 中。

查找中位数

  • 若两个堆的大小相同,中位数是两个堆顶元素的平均值。

  • 否则,中位数是 left 堆的顶元素。
class MedianFinder
{
    priority_queue<int> left; // 大根堆
    priority_queue<int, vector<int>, greater<int>> right; // 小根堆

public:
    MedianFinder() {}

    void addNum(int num)
    {
        // 分类讨论即可
        if(left.size() == right.size()) // 左右两个堆的元素个数相同
        {
            if(left.empty() || num <= left.top()) // 放 left 里面
            {
                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();
    }
};

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

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

相关文章

【Jenkins】data stream error|Error cloning remote repo ‘origin‘ 错误解决【亲测有效】

错误构建日志 17:39:09 ERROR: Error cloning remote repo origin 17:39:09 hudson.plugins.git.GitException: Command "git fetch --tags --progress http://domain/xxx.git refs/heads/*:refs/remotes/origin/*" returned status code 128: 17:39:09 stdout: 17…

unity报错出现Asset database transaction committed twice!

错误描述&#xff1a; 运行时报错 Assertion failed on expression: ‘m_ErrorCode MDB_MAP_RESIZED || !HasAbortingErrors()’Asset database transaction committed twice!Assertion failed on expression: ‘errors MDB_SUCCESS || errors MDB_NOTFOUND’ 解决办法&…

基于springboot实现驾校信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现驾校信息管理系统演示 摘要 随着人们生活水平的不断提高&#xff0c;出行方式多样化&#xff0c;也以私家车为主&#xff0c;那么既然私家车的需求不断增长&#xff0c;那么基于驾校的考核管理也就不断增强&#xff0c;那么业务系统也就慢慢的随之加大。信息…

mac删除带锁标识的app

一 、我们这里要删除FortiClient.app 带锁 常规方式删除不掉带锁的 app【如下图】 二、删除命令&#xff0c;依次执行即可。 /bin/ls -dleO /Applications/FortiClient.app sudo /usr/bin/chflags -R noschg /Applications/FortiClient.app /bin/ls -dleO /Applications/Forti…

C语言【典型算法编程题】总结

以下最全总结! 一,分支结构 1,if 编写程序,从键盘上输入三角形的三个边长(实数),判断这三个边能否构成三角形(构成三角形的条件为:任意两边之和大于第三边),如果能构成三角形,则计算三角形的面积并输出(保留2位小数);如果不能构成三角形,则输出“Flase”字符…

idea如何使用,从激活开始

idea到期后激活使用 如何使用 点击阅读 idea分享

【LinuxC】C语言线程(pthread)

文章目录 一、 POSIX 线程库1.1 POSIX标准1.2 Pthreads1.2 数据类型、函数、宏1.21 数据类型1.22 函数1.23 宏 二、创建线程三、线程同步四、线程销毁五、示例5.1 完整示例5.2 信号量示例 本专栏上一篇文章是Windows下&#xff08;MSVC&#xff09;的线程编程&#xff0c;需要的…

ELK日志管理实现的3种常见方法

ELK日志管理实现的3种常见方法 1. 日志收集方法 1.1 使用DaemonSet方式日志收集 通过将node节点的/var/log/pods目录挂载给以DaemonSet方式部署的logstash来读取容器日志,并将日志吐给kafka并分布写入Zookeeper数据库.再使用logstash将Zookeeper中的数据写入ES,并通过kibana…

如何利用百度SEO优化技巧将排到首页

拥有一个成功的网站对于企业和个人来说是至关重要的&#xff0c;在当今数字化的时代。在互联网上获得高流量和优质的访问者可能并不是一件容易的事情&#xff0c;然而。一个成功的SEO战略可以帮助你实现这一目标。需要一些特定的技巧和策略、但要在百度搜索引擎中获得较高排名。…

某狗网翻译接口逆向之webpack扣取

​​​​​逆向网址 aHR0cHM6Ly9mYW55aS5zb2dvdS5jb20 逆向链接 aHR0cHM6Ly9mYW55aS5zb2dvdS5jb20vdGV4dA 逆向接口 aHR0cHM6Ly9mYW55aS5zb2dvdS5jb20vYXBpL3RyYW5zcGMvdGV4dC9yZXN1bHQ 逆向过程 请求方式&#xff1a;POST 参数构成&#xff1a; 【s】 1b921dbefaa8d939afca…

了解常用测试模型 -- 瀑布模型、螺旋模型、增量与迭代、敏捷开发

目录 瀑布模型 开发流程 开发特征 优缺点 适用场景 螺旋模型 开发流程 开发特征 优缺点 适用场景 增量与迭代开发 什么是增量开发&#xff1f;什么是迭代开发&#xff1f; 敏捷开发 什么是敏捷开发四原则&#xff08;敏捷宣言&#xff09;&#xff1f; 什么是 s…

Pytorch从零开始实战21

Pytorch从零开始实战——Pix2Pix理论与实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——Pix2Pix理论与实战内容介绍数据集加载模型实现开始训练总结 内容介绍 Pix2Pix是一种用于用于图像翻译的通用框架&#xff0c;即图像到图像的转换。…

手撕HashMap底层源码 (JDK1.7版本的HashMap)

day27 集合框架 标绿已经学习底层&#xff0c;深入底层主要是研究实现类底层 手撕HashMap底层源码 JDK1.7版本的HashMap 切换版本 原因&#xff1a;jdk1.7和jdk1.8的HashMap不同&#xff08;头插法/尾插法&#xff09; 首先如果没有jdkjre1.7&#xff0c;就安装jdkjre1.7&am…

mysql数据库备份学习笔记

数据库备份 方法1 物理备份&#xff1a;xtrabackup 方法2 逻辑备份 mysqldump 参考备份与恢复的方法&#xff1a; 【MySql】Mysql之备份与恢复_mysql数据库备份与还原-CSDN博客 可以借鉴的物理备份&#xff1a; 思路是 先做一次全量备份&#xff0c;然后每天做一次增量备份…

从大模型到Agentscope——进阶: 容错机制与构建多模态应用

文章目录 容错机制与构建多模态应用高鲁棒的容错机制鲁棒性的挑战可访问性错误规则可解错误&模型可解错误不可解错误 设计理念&#xff1a;多模态 容错机制与构建多模态应用 高鲁棒的容错机制 鲁棒性的挑战 可访问性错误 默认重新调用三次并把报错给打印出来 规则可解错误…

嵌入式单片机学习思路感想分享

今天看到了一个提问,原话如下: 曾经干了8年单片机工程师,对工程师从入门,到入行,再到普通,再到高级,整个路径还算清晰,比如什么阶段,会碰到什么瓶颈,怎么突破,我都经历过。 这个同学,有个典型的问题,就是学得太多且杂了,估计稍微复杂点的项目,做不出来。 现在…

长期护理保险可改善老年人心理健康 | CHARLS CLHLS CFPS 公共数据库周报(3.6)...

欢迎报名2024年“真实世界临床研究”课程&#xff01; 本周郑老师开讲&#xff1a;“真实世界临床研究”培训班&#xff0c;3月16-17日两天&#xff0c;欢迎报名&#xff01; CHARLS公共数据库‍ CHARLS数据库简介中国健康与养老追踪调查(China Health and Retirement Longitud…

.NET高级面试指南专题十八【 外观模式模式介绍,提供了简化的接口,隐藏系统的复杂性】

介绍&#xff1a; 外观模式是一种结构设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用于访问子系统中的一组接口。外观模式定义了一个高层接口&#xff0c;使得子系统更容易使用。 原理&#xff1a; 外观类&#xff08;Facade Class&#xff09;&#xff1a;提供了一…

电脑芯片维修费用、价格方面的处理方法有哪些?

电脑使用时间长了&#xff0c;难免会出现这样或那样的问题。 笔者整理了一些关于电脑芯片维修费用和价格的参考资料&#xff0c;以及简单的处理方法&#xff0c;供大家了解和学习&#xff1a; 1、笔记本电脑芯片维修&#xff1a; 首先检查电脑系统是否完好。 如果是系统软故障…

【Qt】常用控件或属性(1)

需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、QWidget属性一览 二、控件button、属性enabled(可用状态) 三、属性geometry(修改位置和尺寸) 1、QRect类型的结…