算法思想总结:优先级队列

一、最后一块石头的重量

. - 力扣(LeetCode)

        我们每次都要快速找到前两个最大的石头进行抵消,这个时候用优先级队列(建大堆),不断取堆顶元素是最好的!每次删除堆顶元素后,可以自动调整,时间复杂度是logN。

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) 
    {
        //建立优先级队列  大堆
       priority_queue<int> heap;
       for(auto&num:stones) heap.push(num);
       while(heap.size()>1)
       {
        int x=heap.top();
        heap.pop();
        int y=heap.top();
        heap.pop();
        if(x>y) heap.push(x-y); 
       }
       return heap.size()?heap.top():0;//不为空,就返回堆顶元素,为空,就返回0
    }
};

二、数据流中的第K大元素

. - 力扣(LeetCode)

(1)在学习分治专题的时候,我们知道topK问题可以用优先级队列去解决也可以用快速排序的三路划分去解决,并且快速排序反而会更优秀一点,那优先级队列的优势究竟体现在哪里呢??其优势体现在可以不断地去取用堆顶元素或者是加入元素的时候都可以通过用logN的时间复杂度进行调整,而前期建堆也仅仅是N*logN的时间复杂度,而快速排序的三路划分则是一次性的N的时间复杂度,所以长期优先级队列收益高,短期收益快速排序的三路划分收益高。

class KthLargest {
    priority_queue<int,vector<int>,greater<int>> heap;//仿函数
    int k;   //创建一个大小为k的小根堆 堆顶始终是第k大的元素
    //用快速排序算法可以是O(N)的复杂度,但是如果是要频繁去获取,就很显然得依靠优先级队列
public:
    KthLargest(int _k, vector<int>& nums) 
    {
        k=_k; 
       for(auto &val:nums) 
       {
        heap.push(val);
       if(heap.size()>k) heap.pop();//入堆的同时进行向上调整
       }
    }
    int add(int val) 
    {
       heap.push(val);
       if(heap.size()>k)heap.pop();//可能我插入的时候堆里啥也没有
       return heap.top();
    }
};

 三、数据的中位数

. - 力扣(LeetCode)

策略1:存在数组中用sort去排序  —— add(NlogN)  find(1) 

策略2:还是存在数组中,利用插入排序的思想,因为插入之间就已经是有序的了,所以新元素插入时的时间复杂度是插入排序的最好情况O(N)   ——add(N)   find(1)

策略3:优先级队列大小堆维护中位数   add(logN)  find(1)

设计思路:

1、建立left为大根堆,right为小根堆

2、我们的add控制始终保持left的数量要么和right相等,要么比right多一个,为了能够满足在O(1)的复杂度内完成找到中位数的任务,我们希望当left多一个的时候,left堆顶的元素就是中位数,而当left和right相等的时候,中位数就是两个堆的堆顶元素的平均值。

3、为了达到这个目的,我们在时刻控制left和right的数量的同时,一定要保证left里面的元素是小于等于right里面的元素的,所以add要分两种情况去讨论:

情况1:当两个堆的元素个数相等的时候

    (1)如果left为空,或者是add的元素比left的堆顶元素小,那么就让该元素直接进left

    (2)如果add的元素比left的堆顶元素大,那么他也有可能会比right的元素大,所以我们必须要将这个元素丢到right中,但是直接丢就会破坏规则,所以我们要先将add的元素丢到right中进行调整,然后再将right的堆顶元素丢到left中去,保持left和right的数量关系。 (注意,这里的先后顺序很重要,我们不能先将right的堆顶元素丢到left中,然后再将add丢到right中进行调整,因为我们只是知道这个数比left的堆顶元素大,但是他是比right的堆顶元素大还是小我们不得而知,必须要通过他自己的向下调整去选出来)

情况2:当left的元素比right多一个的时候

  (1)如果add的元素比left的堆顶元素大,这个时候无脑进右边就行了。

   (2)如果add的元素比left的堆顶元素小,这个时候我们也得把add的元素丢到left中,然后为了保持数量关系,将调整过后的left的堆顶元素移到right中即可。

细节处理:

1、我们在比较的时候始终实用left的元素进行比较,因为左边不为空的时候右边也可能为空,所以我们如果不用left去比较而是用right去比较,那么还需要多考虑一种边界情况。

2、虽然我们add的都是int类型,但是当两个堆的元素个数相同的时候,我们去取两个堆顶元素取平均值的,而平均值是有可能会出现小数的,所以如果我们还用int的话可能会造成小数点丢失,所以我们在/2的时候变成/2.0,这样结果就会被强转成double;

class MedianFinder {
public:
    MedianFinder() {} //默认初始化不管了
    void addNum(int num) {
       //分类讨论 m==n或者m==n+1
       size_t m=left.size(),n=right.size();
       if(m==n) //m==n->m==n+1
       {
           //如果我比左边的堆顶小,或者是为空,我就进左边
           if(m==0||num<=left.top()) left.push(num);
           else //如果我比堆顶大,那我要进右边,然后把右边的移过来
           {
             right.push(num);
             left.push(right.top());
             right.pop();
           }
       }
       else // m==n+1 ->m==n
       {
          //如果我比左边的小,直接进右边即可
          if(num <= left.top()) 
          {
             left.push(num);
             right.push(left.top());
             left.pop(); 
          }
          else //如果我比左边的大 无脑进右边 
          right.push(num);
       }
    }
    
    double findMedian() 
    { //我们的策略是 m==n 返回堆顶平均值  如果m==n+1 返回左边的堆顶
      if(left.size()>right.size()) return left.top();
      else return (left.top()+right.top())/2.0;
    }
    private:
         priority_queue<int> left;//左边是大根堆
         priority_queue<int,vector<int>,greater<int>> right;///右边是小根堆
};

四、 前K个高频词汇

. - 力扣(LeetCode)

该题是一道非常经典的OJ题,在哈希表章节中介绍了四种解法,运用stl中的不同容器去解决。

算法思想总结:哈希表-CSDN博客

class Solution {
public:
   typedef pair<string,int> PSI;
    struct compare//要注意仿函数要+const修饰,否则可能编译不过
     {
        bool operator()(const PSI&kv1,const PSI&kv2) const
        {
            if(kv1.second==kv2.second) return kv1.first<kv2.first;
            return kv1.second>kv2.second;
        }
     };
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        unordered_map<string,int> countmap;//计数
        for(auto&s:words) ++countmap[s];
        //丢到优先级队列里
        priority_queue<PSI,vector<PSI>,compare> heap;
        for (auto& it : countmap) {
            heap.push(it);
            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;
    }
};

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

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

相关文章

IP地址:网络还是设备的标识符?

在数字化时代&#xff0c;IP地址已成为我们连接互联网、进行信息交流的基石。然而&#xff0c;关于IP地址的分配和来源&#xff0c;很多人可能并不清楚。它究竟是根据网络来分配&#xff0c;还是基于设备来赋予&#xff1f;下面跟着虎观代理小二一起来解析IP地址的奥秘&#xf…

高效使用 Guzzle:POST 请求与请求体参数的最佳实践

介绍 在现代爬虫技术中&#xff0c;高效发送 HTTP 请求并处理响应数据是关键步骤之一。Guzzle 是一个强大的 PHP HTTP 客户端&#xff0c;广泛应用于发送同步和异步请求。本文将介绍如何使用 Guzzle 发送 POST 请求&#xff0c;特别是如何传递请求体参数&#xff0c;并结合代理…

Windows系统安装分布式搜索和分析引擎Elasticsearch与远程访问详细教程

文章目录 前言系统环境1. Windows 安装Elasticsearch2. 本地访问Elasticsearch3. Windows 安装 Cpolar4. 创建Elasticsearch公网访问地址5. 远程访问Elasticsearch6. 设置固定二级子域名 前言 本文主要介绍如何在Windows系统安装分布式搜索和分析引擎Elasticsearch&#xff0c…

HandlerMethodArgumentResolver :深入spring mvc参数解析机制

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; 搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到三十…

[k8s生产系列]:k8s集群故障恢复,etcd数据不一致,kubernetes集群异常

文章目录 摘要1 背景说明2 故障排查2.1 查询docker与kubelet状态2.2 查看kubelet服务日志2.3 重启docker与kubelet服务2.3.1 首先kubelet启动起来了&#xff0c;但是报错master节点找不到2.3.2 查询kubernetes集群服务&#xff0c;发现etcd与kube-apiserver均启动异常 2.4 etcd…

2024年中国网络安全市场全景图 -百度下载

是自2018年开始&#xff0c;数说安全发布的第七版全景图。 企业数智化转型加速已经促使网络安全成为全社会关注的焦点&#xff0c;在网络安全边界不断扩大&#xff0c;新理念、新产品、新技术不断融合发展的进程中&#xff0c;数说安全始终秉承科学的方法论&#xff0c;以遵循…

Rhino 犀牛三维建模工具下载安装,Rhino 适用于机械设计广泛领域

Rhinoceros&#xff0c;这款软件小巧而强大&#xff0c;无论是机械设计、科学工业还是三维动画等多元化领域&#xff0c;它都能展现出其惊人的建模能力。 Rhinoceros所包含的NURBS建模功能&#xff0c;堪称业界翘楚。NURBS&#xff0c;即非均匀有理B样条&#xff0c;是计算机图…

怎样在Python中使用oobabooga的API密钥,通过端口5000获取模型列表的授权

题意&#xff1a; oobabooga-textgen-web-ui how to get authorization to view model list from port 5000 via the oobas api-key in python 怎样在Python中使用oobabooga的API密钥&#xff0c;通过端口5000获取模型列表的授权 问题背景&#xff1a; I wish to extract an…

抬头显示器HUD原理及特性

HUD基本原理 抬头数字显示仪(Head Up Display)&#xff0c;又叫平视显示系统&#xff0c;它的作用&#xff0c;就是把时速、导 航等重要的行车信息&#xff0c;投影到驾驶员前风挡玻璃上&#xff0c;让驾驶员尽量做到不低头、不转头 就能看行车信息。 HUD成像为离轴三反的过程&…

代码随想录算法训练营第2天|LeetCode977,209,59

977.有序数组平方 题目链接&#xff1a; 977. 有序数组的平方 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 视频讲解&#xff1a; 双指针法经典题目 | LeetCode&#xff1a;977.有序数组的平方_哔哩哔哩_bilibili 第一想法 暴力算法肯定是先将元素…

关于软件本地化,您应该了解什么?

软件本地化是调整软件应用程序以满足目标市场的语言、文化和技术要求的过程。它不仅仅涉及翻译用户界面&#xff1b;它包含一系列活动&#xff0c;以确保软件在目标语言环境中可用且相关。以下是您应该了解的有关软件本地化的一些关键方面&#xff1a; 了解范围 软件本地化是…

【软件测试】之黑盒测试用例的设计

&#x1f3c0;&#x1f3c0;&#x1f3c0;来都来了&#xff0c;不妨点个关注&#xff01; &#x1f3a7;&#x1f3a7;&#x1f3a7;博客主页&#xff1a;欢迎各位大佬! 文章目录 1.测试用例的概念2.测试用例的好处3. 黑盒测试用例的设计3.1 黑盒测试的概念3.2 基于需求进行测…

暗潮短视频:成都柏煜文化传媒有限公司

暗潮短视频&#xff1a;涌动的新媒体力量 在数字化时代的浪潮中&#xff0c;短视频以其独特的魅力和无限的潜力&#xff0c;迅速成为新媒体领域的一股强大力量。而在这片繁荣的短视频领域中&#xff0c;成都柏煜文化传媒有限公司“暗潮短视频”以其独特的定位和深邃的内容&…

论文浅尝 | 从最少到最多的提示可在大型语言模型中实现复杂的推理

笔记整理&#xff1a;王泽元&#xff0c;浙江大学博士 链接&#xff1a;https://openreview.net/forum?idWZH7099tgfM 1. 动机 尽管深度学习已经取得了巨大的成功&#xff0c;但它与人类智慧仍然存在一些明显差距。这些差距包括以下几个方面&#xff1a;1&#xff09;学习新任…

损失函数篇

损失函数 1、边界框损失函数/回归损失函数bbox_loss 2、分类损失函数cls_loss 3、置信度损失函数obj_loss YOLOv8损失函数 1、概述 通过YOLOv8-训练流程-正负样本分配的介绍&#xff0c;我们可以知道&#xff0c;经过预处理与筛选的过程得到最终的训练数据&#xff1a; a…

11 UDP的可靠传输协议QUIC

1.如何做到可靠性传输 2.UDP与TCP,我们如何选择 3.UDP如何可靠,KCP协议在哪些方面有优势 4.KCP协议精讲(重点讲解 5.OUIC时代是否已经到来 UDP如何做到可靠传输 ACK机制重传机制 重传策略序号机制(后发的包可能先到) 3 2 1-> 2 3 1重排机制 2 3 1-> 3 2 1窗口机制 流…

谷粒商城笔记-03-分布式基础概念

文章目录 一&#xff0c;微服务二&#xff0c;集群、分布式三&#xff0c;远程调用四&#xff0c;负载均衡五&#xff0c;服务注册、服务发现、注册中心六&#xff0c;配置中心七&#xff0c;服务熔断、服务降级1&#xff0c;服务熔断2&#xff0c;服务降级3&#xff0c;区别 八…

Spring框架的学习前言

1.注意事项 1.在接下来的学习中我们会将jdk的版本升级到17。 2.引入maven仓库用来存储依赖 3.在后面的javaSpring框架中要第一个项目的创建要选javaweb和lombook这两个依赖 2.Maven的主要功能 &#xff08;1&#xff09;maven的主要功能是引入依赖和管理依赖&#xff0c;在…

基于SpringCloud的分布式架构网上商城

基于SpringCloud的分布式架构网上商城的主要使用者管理员功能&#xff1a;首页、个人中心、用户管理、商品信息管理、商品分类管理、系统管理、订单管理等功能。 &#x1f495;&#x1f495;作者&#xff1a;Weirdo &#x1f495;&#x1f495;个人简介&#xff1a;擅长Java、C…

【SkiaSharp绘图15】SKPath属性详解:边界、填充、凹凸、类型判断、坐标、路径类型

文章目录 SKPath 构造函数SKPath 属性Bounds 边界(宽边界)TightBounds紧边界FillType填充方式IsConcave 是否凹/ IsConvex 是否凸IsEmpty是否为空IsLine是否为线段IsRect是否为矩形IsOval是否为椭圆或圆IsRoundRect是否为圆角矩形Item[] 获取路径的坐标LastPoint最后点的坐标Po…