刷题day11 栈与队列下【逆波兰表达式求值】【滑动窗口最大值】【前 K 个高频元素】

⚡刷题计划day11 栈与队列继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

目录

⚡刷题计划day11 栈与队列继续,可以点个免费的赞哦~

往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

题目一:150. 逆波兰表达式求值

题目二:239. 滑动窗口最大值

题目三:347. 前 K 个高频元素


题目一:150. 逆波兰表达式求值

这不仅仅是一道经典好题,也展现出计算机的思考方式

  1. 逆波兰表达式求值

(https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/)

逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。

该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

  • 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中


主要思路:

了解逆波兰表达式后,思路便很清晰了:

遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中

需要注意:

注意辨析哪个数在运算符左边右边,因为用的栈的数据结构,原左边的数先进栈,运算符右边的数后进栈;

那么出栈pop时先出的就是后进的数,及运算符右边的数

AC代码如下:

class Solution {public int evalRPN(String[] tokens) {
​Deque<Integer> deque = new LinkedList();
​for(String s : tokens){if("+".equals(s)){deque.push(deque.pop()+deque.pop());}else if("-".equals(s)){deque.push(-deque.pop()+deque.pop());}else if("*".equals(s)){deque.push(deque.pop()*deque.pop());}else if("/".equals(s)){int temp1 = deque.pop();int temp2 = deque.pop();deque.push(temp2/temp1);}else {  deque.push(Integer.valueOf(s));}}return deque.pop();
​}
}

题目二:239. 滑动窗口最大值

  1. 滑动窗口最大值

(https://leetcode.cn/problems/sliding-window-maximum/description/)

滑动窗口最大值问题是一个典型的双端队列应用场景。

主要思路:

下面以箱子拿苹果举例,更加通俗易懂:

  1. 箱子(双端队列):你用一个特殊的箱子来装苹果,这个箱子两头都可以拿苹果,我们称之为“双端队列”。

  2. 保持苹果大小顺序:你决定只把大苹果放在箱子的前面,小苹果放在后面。这样,每次你从箱子前面拿苹果,都能保证拿到的是最大的苹果。

  3. 处理新苹果:每当你拿到一个新苹果时,你会做以下事情:

    • 移除小苹果:你检查箱子后面的苹果,如果新苹果比箱子后面的苹果大,你就会把箱子后面的小苹果拿出来扔掉,因为这些小苹果不可能是接下来你拿苹果时的最大苹果了。

    • 放入新苹果:然后,你把新苹果放到箱子的后面。

  4. 移动箱子:随着你不断拿苹果,你也会移动箱子,让箱子前面的苹果(已经被你拿过的)逐渐移出箱子。

  5. 记录最大苹果:每次你移动箱子后,箱子前面的苹果就是当前箱子里最大的苹果,你把它记录下来。

  6. 重复:你重复这个过程,直到所有的苹果都被你检查过。

AC代码及注释如下:

class Solution {public int[] maxSlidingWindow(int[] nums, int k) {Deque<Integer> deque = new ArrayDeque<>(); // 创建一个双端队列int n = nums.length; int[] res = new int[n-k+1]; // 存储结果的数组,长度为 n - k + 1
​for (int i = 0; i < n; i++) {// 维护队列的单调性while (!deque.isEmpty() && nums[deque.getLast()] <= nums[i]) {deque.removeLast(); // 如果队列的最后一个元素的值小于等于当前元素,则移除}deque.addLast(i); // 将当前索引 i 加入队列
​// 维护队列的窗口大小if (i - deque.getFirst() >= k) { // 如果队列的第一个元素已经不在窗口内,则移除deque.removeFirst();}
​// 记录答案if (i >= k - 1) {// 当窗口已经形成,记录队列第一个元素的值作为当前窗口的最大值res[i - k + 1] = nums[deque.getFirst()];}}return res; // 返回结果数组}
}

题目三:347. 前 K 个高频元素

  1. 前 K 个高频元素

(https://leetcode.cn/problems/top-k-frequent-elements/description/)

主要思路

这道题目主要涉及到如下三块内容:

  1. 要统计元素出现频率

  2. 对频率排序

  3. 找出前K个高频元素

首先统计元素出现的频率,这一类的问题可以使用map来进行统计,key-value。

然后是对频率进行排序,这里我们可以使用一种 容器适配器就是优先级队列

什么是优先级队列呢?

其实就是一个披着队列外衣的堆,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。

而且优先级队列内部元素是自动依照元素的权值排列。那么它是如何有序排列的呢?

缺省情况下priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。

什么是堆呢?

堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。

所以大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。

本题我们就要使用优先级队列来对部分频率进行排序。

为什么不用快排呢, 使用快排要将map转换为vector的结构,然后对整个数组进行排序, 而这种场景下,我们其实只需要维护k个有序的序列就可以了,所以使用优先级队列是最优的。

此时要思考一下,是使用小顶堆呢,还是大顶堆?

有的同学一想,题目要求前 K 个高频元素,那么果断用大顶堆啊。

那么问题来了,定义一个大小为k的大顶堆,在每次移动更新大顶堆的时候,每次弹出都把最大的元素弹出去了,那么怎么保留下来前K个高频元素呢。

而且使用大顶堆就要把所有元素都进行排序,那能不能只排序k个元素呢?

所以我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。

寻找前k个最大元素流程如图所示:(图中的频率只有三个,所以正好构成一个大小为3的小顶堆,如果频率更多一些,则用这个小顶堆进行扫描)

AC代码及注释如下:

class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数for(int num : nums){map.put(num,map.getOrDefault(num,0)+1);}// 优先队列默认大根堆,我们需要小根堆// lambda 表达式设置优先级队列从大到小存储 o1 - o2 为从小到大,o2 - o1 反之//在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)-> pair1[1]-pair2[1]);
​for(Map.Entry<Integer,Integer> entry : map.entrySet()){if(pq.size()<k){pq.add(new int[]{entry.getKey(),entry.getValue()});}else {//pq.peek()[1]这个表达式获取peek()方法返回的数组的第二个元素,即队列头部元素的出现次数。if(entry.getValue()>pq.peek()[1]){//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;
​}
}

栈和队列专题就结束了,下期我们开始二叉树专题,加油加油!
赞赞+关注~

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

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

相关文章

无心剑七绝《华夏中兴》

七绝华夏中兴 长空万里尽春声 治世群英喜纵横 一代雄才华夏梦 中兴日月照前程 2024年10月1日 平水韵八庚平韵 无心剑的七绝《华夏中兴》通过对自然景观和国家景象的描绘&#xff0c;展现了一种恢弘的气势和对未来的美好愿景。 意境开阔&#xff1a;首句“长空万里尽春声”以广阔…

MATLAB数字水印系统

课题介绍 本课题为基于MATLAB的小波变换dwt和离散余弦dct的多方法对比数字水印系统。带GUI交互界面。有一个主界面GUI&#xff0c;可以调用dwt方法的子界面和dct方法的子界面。流程包括&#xff0c;读取宿主图像和水印图像&#xff0c;嵌入&#xff0c;多种方法的攻击&#xf…

跳台阶问题

剑指offer的一道简单题目。 描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法&#xff08;先后次序不同算不同的结果&#xff09;。 数据范围&#xff1a;1≤n≤40 要求&#xff1a;时间复杂度&#xff1a;O(n) &a…

C#和Python共享内存技术

我这里做一个简单的示例 1.C#写入内存的方法&#xff0c;FileName是内存共享的名字 t是内存size public static void SaveGluePLYToMemory(string FileName, string msg){try{ long t 100;// SetMemorySize(msg);// 100;//# 创建内存块&#xff0c;test1,其他语言利用这个内存…

sysbench 命令:跨平台的基准测试工具

一、命令简介 sysbench 是一个跨平台的基准测试工具&#xff0c;用于评估系统性能&#xff0c;包括 CPU、内存、文件 I/O、数据库等性能。 ‍ 比较同类测试工具 bench.sh 在上文 bench.sh&#xff1a;Linux 服务器基准测试中介绍了 bench.sh 一键测试脚本&#xff0c;它对…

Python库pandas之一

Python库pandas之一 基本数据结构Series构造器属性属性应用函数函数应用 基本数据结构 Pandas提供了两种类型的类来处理数据&#xff1a; Series&#xff1a;保存任何类型数据的一维数组。例如整数、字符串、Python对象等。DataFrame&#xff1a;一种二维数据结构&#xff0c…

ip是可以从能够上网的设备提取吗

是的&#xff0c;IP地址可以从能够上网的设备提取。以下是如何从不同设备提取IP地址的具体方法&#xff1a; 在电脑上提取IP地址 Windows: 打开命令提示符&#xff08;按下 Win R&#xff0c;输入 cmd&#xff0c;按回车&#xff09;。 输入命令 ipconfig&#xff0c;按回车。…

GAMES101(17~18节,物理材质模型)

材质 BRDF 材质&#xff1a;决定了光线与物体不同的作用方式 BRDF定义了物体材质,包含漫反射和镜面部分 BSDF &#xff08;scattering散射&#xff09; BRDF&#xff08;reflect反射&#xff09; BTDF 光线打击到物体上会向四面八方散射 反射 光线打击到物体上反射出去…

IIS开启后https访问出错net::ERR_CERT_INVALID

安装ArcGIS server和portal等&#xff0c;按照说明上&#xff0c;先开启iis&#xff0c;在安装server、datastore、portal、webadapter等&#xff0c;遇到一些问题&#xff1a; 问题1 访问http正常&#xff0c;访问https出错&#xff1a; 解决方案 从这里找到解决方案&…

【Android 源码分析】Activity生命周期之onPause

忽然有一天&#xff0c;我想要做一件事&#xff1a;去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

java多线程-1-测试一个多线程程序

多线程基本概念 进程&#xff1a;程序的基本执行实体 线程&#xff1a;操作系统能够进行运算调度的最小单位&#xff0c;包含在进程之中 多线程&#xff1a;在等待线程的时间&#xff0c;处理其他线程&#xff0c;提高计算机处理效率以减小资源的占用 并发&#xff1a;在同一时…

【QT】QWidget 重要属性

文章目录 enabledgeometrywindowTitlewindowIconqrc 机制windowOpacitycursorfontQFont toolTip 和 toolTipDurationfocusPolicyQt::FocusPolicy styleSheet enabled 作用&#xff1a;设置控件是否可使用. true 表⽰可用, false 表⽰禁用. 对应的API bool isEnabled(); // 获…

揭秘遗传之谜:自闭症的遗传因素分析

在星贝育园这片充满爱与希望的土地上&#xff0c;我们不仅见证了无数自闭症儿童在康复训练中的点滴进步&#xff0c;更深刻理解了自闭症这一复杂疾病的多样性和挑战性。自闭症&#xff0c;也称为孤独症&#xff0c;是一种影响社交互动、语言和非语言交流以及行为模式的神经发育…

C++ 语言特性06 - lambda表达式

一&#xff1a;概述 1. 语法 [ captures ] ( params ) specifiers exception -> ret { body }其中&#xff1a;captures 是捕获列表&#xff0c;用于捕获当前函数作用域的变量&#xff0c;分为按值捕获和按引用捕获。params 是可选参数列表&#xff0c;和普通函数一样。spe…

通信工程学习:什么是CSMA/CA载波监听多路访问/冲突避免

CSMA/CA&#xff1a;载波监听多路访问/冲突避免 CSMA/CA&#xff08;Carrier Sense Multiple Access/Collision Avoidance&#xff09;&#xff0c;即载波监听多路访问/冲突避免&#xff0c;是一种用于数据传输时避免各站点之间冲突的算法&#xff0c;尤其适用于无线局域网&…

python格式化输入输出

以下是使用 format()、f-string 和百分号 % 运算符进行 Python 数据格式化输入输出的示例代码。 1. 使用 format() 方法进行格式化 # 使用 format() 方法格式化数据并输出到文件 name "Alice" age 25 score 92.5# 格式化字符串 formatted_string "Name: {…

2022年6月 Frontier 获得性能第一的论文翻译

为百万兆级加速架构做高性能 Linpack 优化 摘要 我们详细叙述了在 rocHPL 中做的性能优化&#xff0c;rocHPL 是 AMD 对 HPL 基准的开源实现&#xff0c;主要是针对节点进行优化的架构&#xff0c;是为百万兆级系统而设计的&#xff0c;比如&#xff1a;Frontier suppercomput…

深蕾半导体Astra™ SL1620详细介绍,嵌入式物联网处理器

一&#xff0c;SL1620是什么 Astra™ SL系列是深蕾半导体推出的高度集成的嵌入式物联网处理器SoC&#xff08;System on Chip&#xff09;系列产品&#xff0c;专为多模式消费者、企业和工业物联网工作负载而设计。SL1620是Astra™ SL系列中的一款成本和功耗优化的安全嵌入式So…

Windows 11 安装配置 Git 教程

目录 Git Windows 11 环境安装配置 Git Git Git是一个开源的分布式版本控制系统&#xff0c;由Linus Torvalds创建&#xff0c;用于有效、高速地处理从小到大的项目版本管理。Git是目前世界上最流行的版本控制系统&#xff0c;广泛应用于软件开发中。 以下是Git的一些关键特…

【C#】CacheManager:高效的 .NET 缓存管理库

在现代应用开发中&#xff0c;缓存是提升性能和降低数据库负载的重要技术手段。无论是 Web 应用、桌面应用还是移动应用&#xff0c;缓存都能够帮助减少重复的数据查询和处理&#xff0c;从而提高系统的响应速度。然而&#xff0c;管理缓存并不简单&#xff0c;尤其是当你需要处…