热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LeetCode笔记:剑指Offer41.数据流中的中位数(Java、堆、优先队列、知识点)

本文介绍了LeetCode剑指Offer41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。


文章目录

  • 题目描述
      • 知识点
          • 1. 优先队列
          • 2. Java 中 queue 的 offer、poll 等区别
  • 思路 && 代码
      • 二刷


打卡第十一天~



题目描述


  • 虽然但是,这是一道很nice的题目(涉及的知识点、运用很实用,见知识点模块)
    在这里插入图片描述
    在这里插入图片描述

知识点


1. 优先队列

  • priorityQueue 是 Queue 接口的实现,可以对其中元素进行排序
  • 默认顺序是升序;采用的是堆排序(小顶堆),因此只能保证根是最值,整个堆并不是有序的。
  • 自定义比较类:在 priorityQueue 的构造函数参数中用 Lambda 表达式表示即可。

2. Java 中 queue 的 offer、poll 等区别

  • add、offer:都是添加;队满情况 add 抛出异常,而 offer 则返回 false,可用于判断
  • remove、poll:都是删除首元素;队空情况remove抛出异常,而 poll 返回 null
  • element、peek:都是查询首元素;队空情况element抛出异常,而peek 返回 null

思路 && 代码


  • 代码量不大,主要考察的思路~
  • 首先中位数需要考虑总数奇偶情况:奇取中值,偶取平均值。
  • 然后既然想获得好的时间复杂度,那就空间换时间了(否则数组慢慢来也行了)
  • 接着,既然中位数是在排序后元素集的中间,那么我们可以有这么一个考虑:中间靠两个数据结构实现(毕竟一半一半嘛!),而有序(或局部有序)的数据结构中,进行 add 操作的时间复杂度最低的(O(logn))就是堆了!
  • 因此,我们选取优先队列来作为实现的数据结构~
  • 主要思路:大顶堆存储较小部分,小顶堆存储较大部分。通过两个堆的堆顶来取中位数。通过先添加到堆a,再添加堆a的堆顶到堆b的“洗元素”方式来维护较大较小的属性。

class MedianFinder {Queue<Integer> smallHeap, bigHeap;/** initialize your data structure here. */public MedianFinder() {// 各存一半&#xff1a;small 小顶堆存储较大部分&#xff1b;big 大顶堆存储较小部分smallHeap &#61; new PriorityQueue<>();bigHeap &#61; new PriorityQueue<>((x, y) -> (y - x));}// 维护两个 Heap 的较大、较小属性&#xff1a;O(logn)public void addNum(int num) {// N &#61; 奇数&#xff1a;增加 bigHeap 元素&#xff0c;通过先添加到 smallHeap&#xff0c;再获取其堆顶实现if(smallHeap.size() !&#61; bigHeap.size()) {smallHeap.add(num);bigHeap.add(smallHeap.poll());} // N &#61; 偶数&#xff1a;增加 small 元素&#xff0c;通过先添加到 bigHeap&#xff0c;再获取其堆顶实现else {bigHeap.add(num);smallHeap.add(bigHeap.poll());}}// O(1)public double findMedian() {// 偶数情况if(smallHeap.size() &#61;&#61; bigHeap.size()) {// 较大堆的最小值 &#43; 较小堆里的最大值return (smallHeap.peek() &#43; bigHeap.peek()) / 2.0;}// 奇数情况else {return smallHeap.peek();}}
}/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder obj &#61; new MedianFinder();* obj.addNum(num);* double param_2 &#61; obj.findMedian();*/

二刷


  • 关键词&#xff1a;优先队列、堆之间洗数据、Lambda 表达式
  • 思路还是难忘&#xff0c;代码也不多。这道题保持 hard 的时间估计不长了…

class MedianFinder {Queue<Integer> smallTop &#61; new PriorityQueue<>();Queue<Integer> bigTop &#61; new PriorityQueue<>((x, y) -> (y - x));public MedianFinder() {}public void addNum(int num) {if(smallTop.size() &#61;&#61; bigTop.size()) {bigTop.add(num);smallTop.add(bigTop.poll());}else {smallTop.add(num);bigTop.add(smallTop.poll());}}public double findMedian() {if(smallTop.size() &#61;&#61; bigTop.size()) {return (smallTop.peek() &#43; bigTop.peek()) / 2.0;}else {return smallTop.peek();}}
}

推荐阅读
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • Java编程实现邻接矩阵表示稠密图的方法及实现类介绍
    本文介绍了Java编程如何实现邻接矩阵表示稠密图的方法,通过一个名为AMWGraph.java的类来构造邻接矩阵表示的图,并提供了插入结点、插入边、获取邻接结点等功能。通过使用二维数组来表示结点之间的关系,并通过元素的值来表示权值的大小,实现了稠密图的表示和操作。对于对稠密图的表示和操作感兴趣的读者可以参考本文。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
author-avatar
用户tbz3kln7yj
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有