推广 热搜: page  关键词  链接  搜索  红书  获取  哪些  数据分析  服务  数据 

代码随想录day11 | leetcode150. 逆波兰表达式求值 239. 滑动窗口最大值 347.前 K 个高频元素 栈与队列总结

   日期:2024-12-14     作者:nlhhk    caijiyuan   评论:0    移动:https://sicmodule.kub2b.com/mobile/news/7885.html
核心提示:逆波兰表达式求值即后缀表达式 不用括号 易于计算机计算的表达式注意 因为两个数中是第二个数先弹出 在减法中是被减数 除法是被

逆波兰表达式求值即后缀表达式 不用括号 易于计算机计算的表达式

 

注意

因为两个数中是第二个数先弹出 在减法中是被减数 除法是被除数 所以要特殊处理保证运算顺序。

在编程语言中, 和 的使用主要取决于所使用的语言和它们的功能区别。以下是它们的常见用法对比

1. (双引号
  • 用于表示字符串( 类型)。
  • 字符串是多个字符的组合,长度可以是零或任意多个字符。

示例

 
2. (单引号
  • 用于表示字符( 类型)。
  • 字符只能是单个字符。

示例

 
注意
  • 使用表示多个字符会导致编译错误。
 

总结

语言(双引号(单引号Java表示字符串)表示字符Python表示字符串,无区别表示字符串,无区别JS表示字符串,无区别表示字符串,无区别SQL表示标识符(表名或列名)表示字符串C语言表示字符串(字符数组)表示单个字符

选择还是,需要根据具体语言和语义要求决定。如果是 Java,它们的功能是明确区分的:表示字符串,表示单个字符。


所以** 和 不能互换**。因为这是在 Java, Java 对这两者的用法有严格区分

原因分析
  1. 是用来表示字符串( 类型
    • 代码中的 , , , 都是 字符串
    • 它们的类型是 ,用于和输入的 (字符串数组中的元素)进行比较。
  2. 是用来表示字符( 类型
    • 如果你使用 替换,比如把 改成 ,会导致编译错误。
      因为:- 是一个字符)。
      • 是一个字符串)。
      • 和 是不同的类型,不能直接互换。

示例错误代码

将 替换为

 
编译错误信息
 
  • 这是因为 方法是 的方法,不能对基本数据类型 使用。

正确做法

在 Java 中

  • 保留 表示字符串,例如:。
  • 如果一定要用 ,需要将输入也改为字符类型,并用 比较。但这会改变代码逻辑,需要额外处理输入的解析和转换。

构造单调队列

代码解析

定义变量
 
    • 双端队列,存储数组下标(而非值)。
    • 队列中的下标表示可能的滑动窗口最大值候选元素。
    • 单调队列:从队头到队尾对应的值递减。
    • 数组 的长度。
    • 结果数组,存储每个滑动窗口的最大值。
    • 结果数组的当前填充位置。

主循环
 
  1. :- 当前滑动窗口的右边界索引。

每次迭代中,程序保证以下两点

  1. 队列头节点代表当前窗口的最大值。
  2. 队列是一个递减的单调队列,从队头到队尾,数值依次减小。

步骤 1:移除过期的队头
 
  • 检查队列头部的下标是否已经超出当前滑动窗口 的范围。
  • 如果超出,移除队头(队头的元素已经不在窗口中,不能再被考虑)。

步骤 2:保持队列单调递减
 
  • 从队尾开始,移除队列中所有比当前元素 小的下标。
  • 因为当前元素更大,它会“掩盖”这些较小的元素,不可能再成为最大值候选。

步骤 3:将当前元素加入队列
 
  • 当前元素的下标 加入队列末尾。
  • 确保队列中存储的是滑动窗口的最大值候选下标。

步骤 4:记录结果
 
  • 当窗口的大小达到 (即 )时,开始记录结果。
  • 队头元素 是窗口 的最大值下标,对应的值 是最大值。

最终结果

 

返回结果数组 ,其中存储了每个滑动窗口的最大值。


运行过程示例

假设

解释01[0]队列仅包含第一个元素下标。13[1]1 被 3 覆盖,移除 0,加入 1。2-1[1, 2][3]当前窗口 ,最大值是 (队头下标 1)。3-3[1, 2, 3][3]当前窗口 ,最大值是 (队头下标 1)。45[4][3, 5]超出窗口范围的下标移除, 被 覆盖。53[4, 5][3, 5, 5]当前窗口 ,最大值是 。66[6][3, 5, 5, 6]超出窗口范围的移除, 是新最大值。77[7][3, 5, 5, 6, 7]超出窗口范围的移除, 是新最大值。

最终结果:。

优先级队列(Priority Queue 是一种特殊的队列数据结构,其中每个元素都带有一个优先级按照优先级顺序出队。优先级队列与普通队列的主要区别在于出队的顺序

  • 普通队列是按照元素的入队顺序(FIFO:先进先出)出队。
  • 优先级队列是按照元素的优先级(通常从高到低,或从低到高)出队,而不是入队顺序。

Java中的优先级队列

在 Java 中,优先级队列由 类实现。默认情况下

  • 它是一个最小堆(优先级最低的元素在堆顶)。
  • 元素按自然顺序(或指定的比较器)排序。
常用方法
方法描述 或 将元素插入优先级队列,并维护堆结构。返回队列中的最小元素(不移除)。删除并返回队列中的最小元素(堆顶)。检查队列是否为空。返回队列的元素个数。

示例代码

以下是一个使用 的示例,展示优先级队列的基本操作

 

应用场景

  1. 任务调度:按照任务的优先级处理任务,例如操作系统的进程调度。
  2. 模拟事件驱动系统:在仿真模拟中,优先级队列用于管理事件时间。
  3. 图算法:用于实现 DijkstraPrim 算法,寻找最短路径或最小生成树。
  4. 数据流中实时找最大/最小值:用固定大小的堆实时维护数据流中的最大/最小值。

 

这段代码实现了寻找数组中前 K 个出现频率最高的元素,并使用了 大顶堆(优先级队列 来高效完成任务。以下是对代码的详细解释


问题描述

给定一个整数数组 和一个整数 ,找出数组中出现频率最高的 个元素。


解题思路

  1. 统计频率
    使用一个哈希表)统计每个元素的出现次数。
  2. 使用优先级队列(大顶堆
    • 存储每个元素和其出现次数的二元组。
    • 优先队列会自动按出现次数降序排列。
  3. 取出前 个高频元素
    • 从优先队列中依次弹出 个元素,它们是出现频率最高的 个元素。

代码逐步解析

1. 使用哈希表统计频率
 
  • 遍历 数组,使用 存储每个元素的频率:- Key:元素值。
    • Value:该元素的出现次数。
  • 方法 :- 如果 不在 中,返回默认值 ;否则返回对应的值。

例如
输入 后, 的内容为

 

2. 定义优先队列(大顶堆
 
  • 是 Java 提供的优先级队列类。
  • 比较器 :- 按照二元组的第二个元素(出现次数)降序排列,形成一个 大顶堆
    • 表示优先级从高到低排列。

3. 将频率数据存入优先队列
 
  • 遍历 的键值对,将每个键值对存入优先队列。
  • 队列中存储的是二元组 ,其中:- 是元素值。
    • 是出现次数。

队列内容(按优先级排序

 

4. 弹出前 K 个高频元素
 
  • 从优先队列中弹出 个元素,存入结果数组 。
  • :移除并返回队头元素(出现次数最大的元素)。

例如,若 ,弹出队头两次,得到的结果是

 

返回结果

 

返回存储前 个高频元素的数组。


20.括号匹配问题

括号匹配是使用栈解决的经典问题。
建议要写代码之前要分析好有哪几种不匹配的情况,如果不动手之前分析好,写出的代码也会有很多问题。
先来分析一下 这里有三种不匹配的情况

  1. 第一种情况,字符串里左方向的括号多余了,所以不匹配。
  2. 第二种情况,括号没有多余,但是括号的类型没有匹配上。
  3. 第三种情况,字符串里右方向的括号多余了,所以不匹配。

这里还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了

1047.字符串去重问题

1047 删除字符串中的所有相邻重复项 思路就是可以把字符串顺序放到一个栈中,然后如果相同的话 栈就弹出,这样最后栈里剩下的元素都是相邻不相同的元素了。

150.逆波兰表达式问题

本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么这岂不就是一个相邻字符串消除的过程,和1047.字符串去重问题 中的对对碰游戏是不是就非常像了。

239.滑动窗口最大值问题

运用了一种数据结构:单调队列。
这道题目还是比较绕的,如果第一次遇到这种题目,需要反复琢磨琢磨
主要思想是队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。
那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。C++中没有直接支持单调队列,需要我们自己来一个单调队列
而且不要以为实现的单调队列就是 对窗口里面的数进行排序,如果排序的话,那和优先级队列又有什么区别了呢。
设计单调队列的时候,pop,和push操作要保持如下规则

  1. pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
  2. push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止

保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
一些同学还会对单调队列都有一些困惑,首先要明确的是题解中单调队列里的pop和push接口,仅适用于本题。
单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。
不要以为本题中的单调队列实现就是固定的写法。
我们用deque作为单调队列的底层数据结构,C++中deque是stack和queue默认的底层实现容器(这个我们之前已经讲过,deque是可以两边扩展的,而且deque里元素并不是严格的连续分布的。

347.求前 K 个高频元素

通过求前 K 个高频元素,引出另一种队列就是优先级队列
1.什么是优先级队列呢
其实就是一个披着队列外衣的堆,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。
而且优先级队列内部元素是自动依照元素的权值排列。那么它是如何有序排列的呢
缺省情况下priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。

2.什么是堆呢
堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
所以大家经常说的大顶堆(堆头是最大元素,小顶堆(堆头是最小元素,如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。
本题就要使用优先级队列来对部分频率进行排序。 注意这里是对部分数据进行排序而不需要对所有数据排序
所以排序的过程的时间复杂度是 O(log⁡k) ,整个算法的时间复杂度是 O(nlog⁡k) 。

本文地址:https://sicmodule.kub2b.com/news/7885.html     企库往 https://sicmodule.kub2b.com/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。

 
 
更多>同类最新资讯
0相关评论

文章列表
相关文章
最新动态
推荐图文
最新资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号