算法日记day 14(滑动窗口最大值)

一、滑动窗口最大值

题目:

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       31 [3  -1  -3] 5  3  6  7       31  3 [-1  -3  5] 3  6  7       51  3  -1 [-3  5  3] 6  7       51  3  -1  -3 [5  3  6] 7       61  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

思路:

       采用大顶堆的方法,将滑动窗口所包含的值进行从大到小排序,最大的元素置于队列出口处,若新加入的元素大于入口处元素 ,则将入口的元素弹出,例如:窗口内元素为3,1 这时新加入的元素为2,2>1,因此弹出1,加入2,滑动窗口中的元素更新为3,2,保证队列队顶的元素始终为最大值

代码:

首先定义队列

class MyQueue {Deque<Integer> deque = new LinkedList<>();// 添加元素时,保持队列单调递减的特性void add(int val) {while (!deque.isEmpty() && val > deque.getLast()) {deque.removeLast();}deque.add(val);}// 弹出元素时,如果当前队列头部元素等于给定值,则弹出void poll(int val) {if (!deque.isEmpty() && val == deque.peek()) {deque.poll();}}// 返回队列头部元素(最大值)int peek() {return deque.peek();}
}
  • add(int val): 添加元素时,保证队列中的元素是单调递减的。如果要添加的元素比队列末尾的元素大,就将末尾的元素弹出,直到满足单调递减的条件,然后将新元素加入队列末尾。

  • poll(int val): 弹出元素时,如果当前队列头部元素等于给定值 val,则将其弹出。这是为了确保移除的元素总是当前窗口中的元素。

  • peek(): 返回队列头部元素,即当前窗口中的最大值。

 方法类:

class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 1) {return nums;}int len = nums.length - k + 1;int[] res = new int[len];int num = 0;MyQueue myQueue = new MyQueue();// 初始化第一个滑动窗口for (int i = 0; i < k; i++) {myQueue.add(nums[i]);}res[num++] = myQueue.peek();// 滑动窗口从第二个开始for (int i = k; i < nums.length; i++) {myQueue.poll(nums[i - k]); // 移除窗口最左边的元素myQueue.add(nums[i]); // 添加窗口最右边的元素res[num++] = myQueue.peek(); // 记录当前窗口的最大值}return res;}
}
  • maxSlidingWindow(int[] nums, int k): 这个方法实现了找出数组 nums 中每个滑动窗口的最大值,并将结果存储在数组 res 中返回。

    • 首先判断特殊情况,如果数组长度为1,直接返回数组本身。
    • 计算结果数组 res 的长度 len,即为 nums.length - k + 1
    • 初始化自定义的 MyQueue 对象 myQueue,并将前 k 个元素依次加入队列中。
    • 第一个窗口的最大值通过 myQueue.peek() 获取并存储在 res 中。
    • 从第二个窗口开始遍历数组 nums,每次滑动窗口都先移除左边界元素(使用 myQueue.poll(nums[i - k])),然后加入右边界元素(使用 myQueue.add(nums[i])),再将当前窗口的最大值记录在 res 中。

 

二、前k个高频元素

题目:

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

思路:

遍历所有数中的元素出现的频率并记录,用小顶堆的方法,不断的去比较各元素出现的频率,始终保持堆中保存的是出现次数最大的那个元素

代码:

public int[] topKFrequent2(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数for (int num : nums) {map.put(num, map.getOrDefault(num, 0) + 1);}//在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数//出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆)PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);for (Map.Entry<Integer, Integer> entry : map.entrySet()) { //小顶堆只需要维持k个元素有序if (pq.size() < k) { //小顶堆元素个数小于k个时直接加pq.add(new int[]{entry.getKey(), entry.getValue()});} else {if (entry.getValue() > pq.peek()[1]) { //当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)pq.poll(); //弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了pq.add(new int[]{entry.getKey(), entry.getValue()});}}}int[] ans = new int[k];for (int i = k - 1; i >= 0; i--) { //依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多ans[i] = pq.poll()[0];}return ans;
}

 详细解释:

Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {map.put(num, map.getOrDefault(num, 0) + 1);
}
  • 首先创建一个 HashMap 对象 map,用于统计每个元素出现的频率。遍历数组 nums,对于每个元素 num,使用 map.put(num, map.getOrDefault(num, 0) + 1) 来增加其频率计数。
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);
  • PriorityQueue<int[]> pq:创建一个优先队列,存储 int 数组,这些数组的结构为 {num, count},其中 num 是数组元素,count 是它的出现次数。
  • (pair1, pair2) -> pair1[1] - pair2[1]:这是一个比较器,指定了优先队列的排序方式。具体来说,它按照数组中的第二个元素(即出现次数 count)升序排列,这样堆顶元素始终是出现次数最小的。
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
  • map.entrySet():遍历之前通过哈希映射统计得到的每个元素的频率信息。
if (pq.size() < k) {pq.add(new int[]{entry.getKey(), entry.getValue()});
} else {if (entry.getValue() > pq.peek()[1]) {pq.poll();pq.add(new int[]{entry.getKey(), entry.getValue()});}
}
  • 如果队列未满 (pq.size() < k)

    • 将当前元素 entry.getKey()(元素值)和 entry.getValue()(出现次数)作为一个新的数组 {entry.getKey(), entry.getValue()} 加入优先队列 pq 中。
  • 如果队列已满

    • 检查当前元素的出现次数 entry.getValue() 是否大于堆顶元素的出现次数 pq.peek()[1]
    • 如果是,从堆顶移除最小的元素(即出现次数最少的),然后将当前元素的数组 {entry.getKey(), entry.getValue()} 加入堆中。这样可以保证堆中始终是出现次数最大的前 k 个元素。
int[] ans = new int[k];
for (int i = k - 1; i >= 0; i--) {ans[i] = pq.poll()[0];
}
  • 创建一个大小为 k 的结果数组 ans,从小顶堆中依次弹出元素,将其存入结果数组中。由于小顶堆保证了每次弹出的元素是出现次数最大的前 k 个元素中的一个,因此这些元素按照频率从高到低排列在结果数组中。
return ans;
  • 最后返回结果数组 ans,其中包含了前 k 个高频元素按照频率降序排列的结果。

今天的学习就到这里了 

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

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

相关文章

【测开能力提升-fastapi框架】fastapi能力提升 - ORM增删改查操作

1 ORM操作 注释&#xff1a; fastapi缺少合适的ORM&#xff0c;官方推荐&#xff1a;sqlalchemy&#xff0c;但我们就不听官方的话&#xff0c;我们选择使用Tortoise ORM&#xff0c;因为他是支持异步的 1.1 tortoise ORM支持的数据库 PostgreSQL&#xff08;使用asyncpg&am…

上市公司产品市场竞争程度指数(1990-2023年)

数据来源&#xff1a;基础数据来源于上市公司年报以及证监会及统计局时间跨度&#xff1a; 1990-2023年数据范围&#xff1a;企业及行业层面数据指标&#xff1a;本数据包含赫芬达尔指数/行业集中度/勒纳指数三个数据: 行业代码 行业名称 统计截止日期 市场类型 是否…

指针!!C语言(第二篇)

目录 一. 数组名的理解 二. 一维数组传参的本质 三. 冒泡排序法 四. 二级指针与指针数组 五. 字符指针变量与数组指针 一. 数组名的理解 在我们对指针有了初步的理解之外&#xff0c;今天我们来掌握一些新的知识就是数组与指针&#xff0c;第一个对数组名的了解&#xff…

Java8-21新特性

简介 由于Java官方最近更新越来越频繁&#xff0c;而长期支持维护的版本LTS版每隔几年才推出一个&#xff0c;大规模商用的JDK只可能选择LTS版&#xff0c;因此这里只简单记录JDK8&#xff0c;11&#xff0c;17&#xff0c;21。 jdk8 Lambda表达式&#xff1a; Lambda表达式…

PyQt5学习路线

后续会根据该文章的路线逐步发布对应的教程&#xff0c;订阅专栏不迷路&#x1f970; 本专栏纯干货&#x1f929; 学习Python的PyQt5库&#xff0c;可以遵循以下的学习路线&#xff1a; 1. Python基础 掌握Python语法&#xff1a;确保你熟悉Python的基本语法&#xff0c;包括…

#三元运算符(python/java/c)

引入&#xff1a;什么是三元运算符呢&#xff1f;无疑其操作元有三个&#xff0c;一个是条件表达式&#xff0c;剩余两个为值&#xff0c;条件表达式为真时运算取第一个值&#xff0c;为假时取第二个值。 一 Python true_expression if condition else false_expressi…

matlab永磁同步电机反馈试验装置的设计和永磁同步电机仿真

1、内容简介 略 85-可以交流、咨询、答疑 2、内容说明 略 摘要&#xff1a;得益于电力电子器件及控制技术的高速发展&#xff0c;使得电机的应用越来越方便及精确&#xff0c;适应了实际应用对电机性能及质量提出的更高要求和标准。同时电机测试技术也因为电力电子技术的发…

2024.7.22

关于DSP资料分享 https://www.youtube.com/watch?vI8_E1ppC3-Q

AI多模态实战教程:面壁智能MiniCPM-V多模态大模型问答交互、llama.cpp模型量化和推理

一、项目简介 MiniCPM-V 系列是专为视觉-语⾔理解设计的多模态⼤型语⾔模型&#xff08;MLLMs&#xff09;&#xff0c;提供⾼质量的⽂本输出&#xff0c;已发布4个版本。 1.1 主要模型及特性 &#xff08;1&#xff09;MiniCPM-Llama3-V 2.5&#xff1a; 参数规模: 8B性能…

Oracle(6)什么是重做日志文件(Redo Log File)?

重做日志文件&#xff08;Redo Log File&#xff09;是Oracle数据库中用于记录所有对数据库进行的更改的日志文件。这些文件在数据库崩溃恢复、实例恢复和介质恢复中起着至关重要的作用。 主要特点 记录更改&#xff1a;重做日志文件记录了所有对数据库进行的更改&#xff0c…

将Excel或CSV文件导入MySQL

数据库信息 版本:mysql-5.7.22 字符集如下 一、将 Excel 文件导入 MySQL,此时 MySQL 中不存在该表。 在数据库中,右键-导入向导

C++ 入门16:STL 容器之集合(set)与多重集合(multiset)

往期回顾&#xff1a; C 入门13&#xff1a;异常处理-CSDN博客 C 入门14&#xff1a;STL 容器之向量&#xff08;vector&#xff09;-CSDN博客 C 入门15&#xff1a;STL 容器之列表&#xff08;list&#xff09;-CSDN博客 C 入门16&#xff1a;STL 容器之集合&#xff08;set&a…

刚刚 威尼斯影评人周公布 2024 年电影阵容 包括敏感纪录片《本土》

《本土》 威尼斯影评人周是威尼斯电影节专门为首次拍摄电影的人设立的侧边活动&#xff0c;该活动公布了第 39 届威尼斯电影节的七部竞赛片和两部非竞赛片的入选名单&#xff0c;第 39 届威尼斯电影节将于 8 月 28 日至 9 月 7 日举行。 较为及时的作品之一是美国导演迈克尔普…

【IntelliJ IDEA】一篇文章集合所有IDEA的所有设置

IntelliJ IDEA 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;其设置涵盖了多个方面&#xff0c;以满足不同开发者的需求和偏好。由于 IDEA 的设置相当复杂和详尽&#xff0c;这里无法在一篇简短的文章中详细介绍所有设置。然而&#xff0c;我可以提供一…

@SpringBootApplication 注解及源码 详解

SpringBootApplication(scanBasePackages {"com.XXX"}) 标注 启动类注解。 内含源码注解 Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Inherited SpringBootConfiguration EnableAutoConfiguration ComponentScan(excludeFilters …

CSS 计数器:WebKit 的样式增强术

CSS 计数器&#xff1a;WebKit 的样式增强术 CSS 计数器是 CSS2.1 规范中引入的一个强大特性&#xff0c;它允许网页开发者在文档中创建和维护计数器。这些计数器可以用于列表编号、章节编号、图表索引等场景。WebKit 引擎&#xff0c;作为许多流行浏览器&#xff08;如 Safar…

持续集成07--Jenkins配置Allure测试报告

前言 在持续集成&#xff08;CI&#xff09;流程中&#xff0c;自动化测试报告是评估软件质量和追踪问题的重要工具。Allure Framework作为一个轻量级且功能丰富的测试报告工具&#xff0c;能够生成详细的测试报告&#xff0c;帮助团队更好地理解测试结果。本章节“持续集成07-…

Java二十三种设计模式-装饰器模式(7/23)

装饰器模式&#xff1a;动态扩展功能的灵活之选 引言 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;用于在不修改对象自身的基础上&#xff0c;通过添加额外的职责来扩展对象的功能。 基础知识&#xff0c;java设计模式总体来说设计…

特征工程方法总结

方法有以下这些 首先看数据有没有重复值、缺失值情况 离散&#xff1a;独热 连续变量&#xff1a;离散化&#xff08;也成为分箱&#xff09; 作用&#xff1a;1.消除异常值影响 2.引入非线性因素&#xff0c;提升模型表现能力 3.缺点是会损失一些信息 怎么分&#xff1a;…

爬取百度图片,想爬谁就爬谁

前言 既然是做爬虫&#xff0c;那么肯定就会有一些小心思&#xff0c;比如去获取一些自己喜欢的资料等。 去百度图片去抓取图片吧 打开百度图片网站&#xff0c;点击搜索xxx&#xff0c;打开后&#xff0c;滚动滚动条&#xff0c;发现滚动条越来越小&#xff0c;说明图片加载…