算法通过村第十四关-堆|白银笔记|经典问题

文章目录

  • 前言
  • 在数组中寻找第K大的元素
  • 堆排序原理
  • 合并K个排序链表
  • 总结


前言


提示:想要从讨厌的地方飞出来,就得有藏起来的翅膀。 --三岛由纪夫《萨德侯爵夫人》

这里我们主要看一下经典的题目,这三个题目来说都是堆的热点问题。重点再理解处理方式就行。

在数组中寻找第K大的元素

参考题目地址:215. 数组中的第K个最大元素 - 力扣(LeetCode)
在这里插入图片描述

在这里插入图片描述

这个题目的道理非常简单,主要的方法有三种:

  1. 选择法
  2. 堆查找法
  3. 快速排序法

选择法很简单,就是遍历一边找到最大的元素,然后再遍历一遍找第二大的,然后再遍历一遍找第三大…直到第K次,就可以找到目标值。但是这种方法只适合面试的时候预热,面试官不会让你写这么简单的代码,因为这个方法的时间复杂度为O(NK)。

比较好的方法就是堆排序和快速排序。快速排序我们已经分析过了,这里看看堆排序的,看看怎么解决。

快排推荐⭐⭐⭐⭐:算法通过村第十关-快排|青铜笔记|快排也没那么难-CSDN博客

其实这个题目采用大顶堆和小顶堆都是可以解决的,但是我们这里推荐**“找最大用最小,找最小用最大”**,找中间用两个堆呗,这样更容易理解,适用的范围也更广。我们构造一个大小只有4的小顶堆,为了更好说明问题,我们扩展以下序列:【3,2,3,1,2,4,5,1,5,6,2,3】。

堆满了之后,对于小顶堆,并一定所有新来的元素都可以入堆的,只有大于根元素的才可以插入到堆中,否则就直接抛弃掉。这是一个重要的前提。

另外元素进入的时候,先替换根元素,如果发现左右两个子树都小该怎么办呢?很显然应该是更小的那个比较,这样才能保证根元素一定是当前堆最小的。假如两个子孩的值一样呢?那就随便选一个。

在这里插入图片描述

新元素插入的时候只是替换根元素,然后重新构造小顶堆,完成之后,你会神奇的发现此时根的元素正好是第四大的元素。

这时候你会发现,不管要处理多大的序列,或者是不是固定的,根元素每次都是恰好是当前序列下的第K大的元素。上面图的篇幅优先,注意省略了一部分调成的环节,这里好好看看。

上面的代码自己实现起来非常困难,我们可以借助JDK的优先队列来解决,其思路是很简单的。由于第K大的元素,其实就是整个数组排序以后后面半部分最小的那个元素,这里就可以注意,我们可以维护一个有K个元素的最小堆:

  • 如果当前堆不满,直接添加
  • 堆满的时候,如果新读到的数小于等于堆顶,肯定不是我们要找的元素,只有新遍历到的数大于堆顶的时候,才能将堆顶拿出,然后放入新读到的数,进而让堆自己去调整内部的结构。

说明:这里最适合的操作其实是replace(),即直接把新读到的元素放入堆顶,然后执行下沉(siftDown())操作。Java中PriorityQueue没有提供这个操作,只好先poll再offer

优先队列的写法有很多,这里只例举一个有代表性,其他的写法都差不多,没有本质区别。

看代码如下:

    /*** 数组中的第K个最大元素* @param nums* @param k* @return*/public static int findKthLargest(int[] nums, int k) {// 当然k不合理,就直接结束if (k > nums.length) {return -1;}// 获取数组长度int n = nums.length;// 创建包含k个元素的小顶堆PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a, b) -> a - b);for (int i = 0; i < k; i++) {minHeap.add(nums[i]);}for (int i = k; i < n; i++) {// 获取堆顶元素 比较是否需要替换Integer topEle = minHeap.peek();// 这里只有大于 才能进if (nums[i] > topEle) {minHeap.poll();minHeap.offer(nums[i]);}}return minHeap.peek();}

堆查找与一般的查找一个显著的优势点是可以对于超大数量的数据进行查找,还能堆数量位置的流数据进行查找。推荐一个题目⭐⭐⭐⭐:

703. 数据流中的第 K 大元素 - 力扣(LeetCode)

这里重要的是记住:找第k大用小顶堆,找第K小用大顶堆。

具体来说:

k多大就建立多大的固定堆
找最大用小顶堆
只和根元素比较,满足条件在能进去

堆排序原理

查找:找小用大,找大用小

排序:升序用小,降序用大

前面介绍了如何使用堆来进行特殊情况的查找,堆的另一个很重要的作用就是排序,那么要怎么排序呢?其实非常简单,我们直到再大顶堆中,根节点是整个结构最大的元素,我们将其拿走,剩下的元素将会重排,此时根节点的第二大的元素,我们再拿走,依次类推。最后堆只剩一个元素的时候,是不是拿走的数据也就排好了?

具体来说,建堆结束之后,数组中的数据已经按照大顶堆的特性来组织了,数组中的第一个元素就是堆顶,也就是最大元素,我们只要他和最后一个元素交换,那个最大元素就放到下标为n的位置上了。

这个过程上面有点类型“删除堆顶元素”的操作,当堆顶元素移除之后,我们把剩下标为n的元素放到堆顶,然后再通过堆的结构化调整,将剩下的n - 1个元素重新构建成堆,堆调整之后,我们再去取元素,这样一直循环,直至重复下去,直到堆最后剩下一个元素,也就是排序完成了。

当然再上面的过程用,放到最后一个位置的元素就不参与排序和计算了。

看一个例子,我们对一个序列进行排序[2,21,4,53,64,78,90,102],先构造大顶堆,然后然根元素出堆,继续调整大顶堆:
在这里插入图片描述
这时候你会发现出堆的序列刚好是:102,90,78,64,53…。也就是从大到小排列。

所以这里可以明白了,如果是小顶堆的化,自然是升序的。所以再排序的时候:

升序用小,降序用大。

记住这个对解题很有用。

合并K个排序链表

参考题目介绍:23. 合并 K 个升序链表 - 力扣(LeetCode)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个问题的解法五花八门,我们看下用堆排序要怎么处理,因为每个队列都是从小到大排序的,我们每次需要拿到最小值,也就是说我们需要使用小顶堆,构建党法和操作与大顶堆完全一样,不同的是每次比较谁更小。使用堆和并的策略是不过几个链表,最终都是按照顺序来的。每次都是剩余节点的最小值加到输出链表的尾部,然后进行堆的调整,最后合并就完成了。

还有一个问题,这个堆应该有多大呢,给了对少个链表,堆就定义多大。

    /*** 合并 K 个升序链表** @param lists* @return*/public ListNode mergeKLists(ListNode[] lists) {if (lists.length == 0 || lists == null) {return null;}// 创建堆PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(Comparator.comparing(node -> node.val));for (int i = 0; i < lists.length; i++) {if (lists[i] != null) {q.add(lists[i]);}}// 虚拟节点ListNode dummy = new ListNode(0);ListNode tail = dummy;while (!q.isEmpty()) {tail.next = q.poll();  // 取最小tail = tail.next;      // 链接下一个if (tail.next != null) { // 判断是否到底q.add(tail.next);  // 重复下一个}}return dummy.next;}

总结

提示:堆经典问题;大顶堆和小顶堆;手绘原理;堆排序解析;堆查询特点


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。
在这里插入图片描述

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

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

相关文章

华为发布LampSite X室内数字化创新解决方案,释放数字世界无限潜能

【阿联酋&#xff0c;迪拜&#xff0c;2023年10月11日】2023全球移动宽带论坛&#xff08;Global MBB Forum 2022&#xff09;期间&#xff0c;华为董事、ICT产品与解决方案总裁杨超斌重磅发布了全新一代5G室内数字化产品解决方案LampSite X系列&#xff0c;助力运营商打开商业…

在Unity中挂载C#脚本的三种方法

第一种 ①在Project&#xff08;工程&#xff09;窗口的某个文件夹中&#xff08;也可以选择新建在Assets&#xff08;资源根目录&#xff09;中&#xff09;&#xff0c;然后单击鼠标右键&#xff0c;选择Create->C# Script 注意&#xff1a;扩展名在Unity编辑器中是隐藏…

C# PortraitModeFilter (人物图片)背景模糊

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Windows.Forms; us…

为什么估计的参数具有渐进高斯性?M-estimateor的渐进高斯性推导

M-estimators 在这里我们研究一种叫M-estimators的渐进高斯性。具体来说&#xff0c;如果参数估计可以用一个最小化或者最大化目标表示&#xff1a; θ o arg ⁡ min ⁡ θ ∈ Θ E [ q ( w , θ ) ] \theta _{o} \arg\min_{\theta \in \Theta }\mathbb{E}[ q(w,\theta )] θ…

【数据结构C/C++】十大排序算法的实现思路以及易写易记忆版代码实现

文章目录 冒泡排序选择排序插入排序归并排序数组版本链表版本 快速排序&#xff08;重点讲解&#xff09;堆排序&#xff08;重点理解&#xff09;408考研各数据结构C/C代码&#xff08;Continually updating&#xff09; 冒泡排序 时间复杂度 O&#xff08;n2&#xff09; 空…

一波三折未挫锐气,友宝在线讲了一个新故事?

2017年&#xff0c;无人零售一度引爆国内零售行业。一时间&#xff0c;无论是老将还是新兵都开始涌入市场&#xff0c;互联网巨头、传统零售企业、新入局的创业者纷纷扎堆。这期间&#xff0c;身为智能零售终端服务商的友宝在线一直在发力寻求突破。 自2019年在新三板摘牌后&a…

Python实现PDF转换文件格式

最近工作中经常遇到收到其他人提供的pdf文档&#xff0c;想要编辑修改下或者复制部分内容比较困难&#xff0c;想通过现有的pdf工具软件转换文档格式&#xff0c;基本都要充钱&#xff0c;为了免费实现pdf转换工具&#xff0c;网上查了下相关技术方案&#xff0c;整理了下代码&…

多模态大模型NextGPT整体结构图、模型示意图和使用模型时示意图

NextGPT模型整体结构 项目地址 论文地址 模型示意图 使用模型时示意图

企业如何凭借软文投放实现营销目标?

数字时代下&#xff0c;软文投放成为许多企业营销的主要方式&#xff0c;因为软文投放成本低且效果持续性强&#xff0c;最近也有不少企业来找媒介盒子进行软文投放&#xff0c;接下来媒介盒子就来给大家分享下&#xff0c;企业在软文投放中需要掌握哪些技巧&#xff0c;才能实…

批量修改视频尺寸:简单易用的视频剪辑软件教程

如果你需要批量修改视频尺寸&#xff0c;同时保持高质量的画质&#xff0c;那么“固乔剪辑助手”这款软件是你的不二之选。下面就是如何使用这款软件进行批量修改视频尺寸的详细步骤。 1. 首先&#xff0c;你需要在浏览器中进入“固乔科技”的官网&#xff0c;然后下载并安装“…

for循环遍历的`form表单组件`rules规则校验失效问题——下拉框选择之后还是报红---亲测有效

问题: 大概的效果就是这种, for循环选择之后还是还是报红 看文章之前 : 先检查 model rules pops 有没有判定好 解决: 参考了他的 for循环遍历的form表单组件rules规则校验失效问题——输入内容后依然提示必填&#xff0c;亲测有效——基础积累_a-form-model的validat…

NFTScan | 10.09~10.15 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期&#xff1a;2023.10.09~ 2023.10.15 NFT 热点资讯 01/ DeLabs&#xff1a;所有 DeGods 已重置回 Season1&#xff0c;用户可于本周将 y00ts 免费迁移至以太坊 10 月 9 日&#xff0c;DeGods & y…

前端小案例 | 一个带切换的登录注册界面(静态)

文章目录 &#x1f4da;HTML&#x1f4da;CSS&#x1f4da;JS &#x1f4da;HTML <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-sc…

HBase 表如何按照某表字段排序后顺序存储的方法?

首先需要明白HBase表的排序规则&#xff1a; &#xff08;1&#xff09;rowkey排序&#xff08;字典排序&#xff09;——升序 &#xff08;2&#xff09;Column排序&#xff08;字典排序&#xff09;——升序 &#xff08;3&#xff09;时间戳排序——降序 rowkey 字典序排序…

SpringMVC的拦截器(Interceptor)

拦截器简介 SpringMVC的拦截器Interceptor&#xff0c;主要是对Controller资源访问时进行拦截的基本操作的技术&#xff0c;当然拦截后可以进行权限控制&#xff0c;功能增强等都是可以的。拦截器类似于JavaWeb开发中的Filter&#xff0c;他们之间的区别如下图所示 Filter技术…

设计模式再探——适配器模式

目录 一、背景介绍二、思路&方案三、过程1.适配器模式简介2.适配器模式的类图3.适配器模式代码4.适配器模式&#xff0c;类适配器模式和对象的对比5.适配器模式终极奥秘 四、总结五、升华 一、背景介绍 最近公司在对业务模型做构建的时候&#xff0c;涉及到和三方系统的对…

学习嵌入式系统的推荐步骤:

学习嵌入式系统的推荐步骤&#xff1a; 00001. C语言&#xff1a;作为基础中的基础&#xff0c;选择一本常用的C语言教材&#xff0c;并注意通过实践编写习题、编译运行代码来加深理解。动手实践是非常重要的。 00002. 00003. 微机原理与接口技术&#xff1a;这本教材将…

Web攻防01-ASP应用相关漏洞-HTTP.SYSIIS短文件文件解析ACCESS注入

文章目录 ASP-默认安装-MDB数据库泄漏下载漏洞漏洞描述 ASP-中间件 HTTP.SYS&#xff08;CVE-2015-1635&#xff09;1、漏洞描述2、影响版本3、漏洞利用条件4、漏洞复现 ASP-中间件 IIS短文件漏洞1、漏洞描述2、漏洞成因:3、应用场景&#xff1a;4、利用工具&#xff1a;5、漏洞…

深入理解Scrapy

Scrapy是什么 An open source and collaborative framework for extracting the data you need from websites. In a fast, simple, yet extensible way. Scrapy是适用于Python的一个快速、简单、功能强大的web爬虫框架&#xff0c;通常用于抓取web站点并从页面中提取结构化的数…

嵌入式软硬分工与职业发展

嵌入式软硬分工与职业发展&#xff1a; 嵌入式系统分为软件和硬件两个方向。大公司通常明确员工从事嵌入式软件或硬件工作&#xff0c;分工合理利用经验解决问题。小公司可能综合工作&#xff0c;但长期不利深入学习和发展&#xff0c;对个人竞争力不利。嵌入式软件一般指底层…