leetcode刷题——栈与队列

2023-11-16

队列 vs 栈

  • 栈:从头进,从头出,只有头部一个进出口
  • 队列:从尾进,从头处,头和尾分别负责出和进。适用于配对问题。

20. 有效的括号
运用栈尾进头出的思想实现配对

  • 当我们遇到一个左括号时,我们会期望在后续的遍历中,有一个相同类型的右括号将其闭合。由于后遇到的左括号要先闭合,因此我们可以将这个左括号放入栈顶stack.append(item)。

  • 当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合。此时,我们可以取出栈顶的左括号stack[-1], 并判断它们是否是相同类型的括号if stack[-1]=item。

    • 如果不是相同的类型,返回 \text{False}False。
    • 或者栈中并没有左括号,那么字符串 ss 无效,返回 \text{False}False。
    • 如果是相同的类型,则删除此配对,并继续遍历

    # 方法一,仅使用栈,更省空间
        stack = []
        for item in s:
        # 左括号
            if item == '(':
                stack.append(')')
            elif item == '[':
                stack.append(']')
            elif item == '{':
                stack.append('}')
            # 右括号
            elif not stack or stack[-1] != item:    # 如果不是相同的类型,或者栈中并没有左括号,那么字符串 ss 无效,返回 \text{False}False。
                return False
            else:
                stack.pop()# 配对成功,删除此配对,继续遍历
        
        return True if not stack else False # 最后True应该是stack为空
        
# 方法二,使用字典
class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        mapping = {
            '(': ')',
            '[': ']',
            '{': '}'
        }
        for item in s:
            if item in mapping.keys():
                stack.append(mapping[item])
            elif not stack or stack[-1] != item:   # 匹配不成功或没有匹配项
                return False
            else:    # 匹配成功
                stack.pop()   
        return True if not stack else False

1047. 删除字符串中的所有相邻重复项
相邻重复运用队列思想,先进后出

  • 匹配成功(重复):删除重复元素stack.pop()
  • 匹配不成功(不重复):加入队列,继续遍历stack.append(s[i])
class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack=[]
        stack.append(s[0])
        for i in range(1,len(s)):
            if stack and stack[-1]==s[i]:stack.pop()
            else:stack.append(s[i])
        return ''.join(stack)

150. 逆波兰表达式求值

  • 代码注意点:把字符串’+‘,‘2’,‘3’转化为数值计算:eval(f’{second_num} {item} {first_num}’)
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack=[]
        for item in tokens:
            if item not in {'+','-','*','/'}:stack.append(item)  # 数字则入栈
            else:    # 符号则计算
                first_num, second_num = stack.pop(), stack.pop()  # 先出两个
                stack.append(int(eval(f'{second_num} {item} {first_num}')))   #再进一个计算结果
        return int(stack.pop())

347. 前 K 个高频元素
【法一】counter计数

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import Counter
        count_dict=sorted(Counter(nums).items(),key=(lambda x:x[1]),reverse=True)  # 根据次数来逆序排序,是列表中元素为元组的形式
        return [x[0] for x in count_dict[:k]]

【法二】heapq求前n个最大/最小值

  • low3 =heapq.nlargest(3, list)
  • top3 = heapq.nsmallest(3, list)
  • heapq.heappush(heaptree,item) # 向堆中加入元素
  • heapq.heapop(heaptree) # 从堆中弹出元素

可以用优先级队列的思想

时间复杂度:O(nlogk)
#空间复杂度:O(n)
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        #要统计元素出现频率
        map_ = {} #nums[i]:对应出现的次数
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1
        
        #对频率排序
        #定义一个小顶堆,大小为k
        pri_que = [] #小顶堆
        
        #用固定大小为k的小顶堆,扫面所有频率的数值
        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                heapq.heappop(pri_que)
        
        #找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒叙来输出到数组
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

字符串解码
(太难了)
递归问题可以用栈来解决,从小问题剖析,先进先出
本题核心思路是在栈里面每次存储两个信息, (左括号前的字符串, 左括号前的数字), 比如abc3[def]:

  • 当遇到字母:记录到res
  • 当遇到数字:记录
  • 当遇到第一个左括号的时候,压入栈中的是(“abc”, 3), 然后遍历括号里面的字符串def
  • 当遇到右括号的时候, 从栈里面弹出一个元素(s1, n1), 得到新的字符串为s1+n1*“def”, 也就是abcdefdefdef。对于括号里面嵌套的情况也是同样处理方式。
    凡是遇到左括号就进行压栈处理,遇到右括号就弹出栈,栈中记录的元素很重要。

stack.pop() 表示读取最后一个值并删除
stack[-1] 表示读取最后一个值

class Solution:
    def decodeString(self, s: str) -> str:
        stack = []  # (str, int) 记录之前的字符串和括号外的上一个数字
        num = 0 # 辅助记录数字
        res = ""  # 实时记录当前可以提取出来的字符串
        for c in s:
            if c.isdigit():  # 是数字  1-
                num = num * 10 + int(c) # 针对两位数,在遍历中读取两位数
            elif c == "[":  # [ 2-
                stack.append((res, num))  # res指的是[之前的正确结果
                res, num = "", 0
            elif c == "]":  # ] 4-
                top = stack.pop()
                res += top[0] + res * top[1]
            else:  # 是字母 3-
                res += c
        return res
       
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

leetcode刷题——栈与队列 的相关文章

随机推荐

  • selenium4

    1 单选框和复选框 单选框 type radio 定位 gt 点击 判断是否被选中 元素 is selected 复选框 type checkbox 只选择一个 gt 同单选框一样 全选 定位所有复选框 遍历 判断是否被选中 点击 选择部分
  • java入门六:java基础终章

    1 static关键字 静态变量和类一起加载 final修饰后的类无法被继承 2 抽象类 abstract修饰符可以用来修饰方法也可以修饰类 如果修饰方法 那么该方法就是抽象方法 如果修饰类 那么该类就是抽象类 抽象类中可以没有抽象方法 但
  • Linux Shell程序设计(2)

    实验十一 Shell程序设计 2 一 实验要求 综合运用shell编程知识进行设计性编程 二 实验内容和实验步骤 1 实验内容 假设你作为某工厂生产管理员 需要负责统计各车间每天生产的产品数据 你的计算机安装了双硬盘 为了保证数据安全 你在
  • 【定位问题】Mybatis-plus的selectPage()分页查询不生效问题

    背景 项目需要从mybits切换到mubits plus 但是我在进行分页查询的时候 发现一直不生效 问题原因 添加监听器 配置如下 Configuration MapperScan com baomidou mybatisplus sam
  • parted创建硬盘分区并创建LVM

    目的 将两个三T的硬盘做成LVM sdc sdd 一 parted将硬盘进行分区 1 parted的命令方式 Parted 命令分为两种模式 命令行模式和交互模式 1 命令行模式 parted option device command 该
  • 【原创】第一个iOS应用程序

    摘要 第一个iOS应用程序 包括获取控件 绑定事件 设置属性等内容 iOS Objective C 目录 第一章 窗口与应用程序 第二章 添加视图 2 1 从nib文件初始化视图 2 2 使用脚本添加视图 第三章 添加子视图 3 1 通过x
  • 制作自己的 Kindle 电子书

    想象以下场景 你刚收到一台新的 Kindle Paperwhite 心中已然响起了轰轰烈烈的 我今年 或这个冬天 一定要阅读 100 本书 结果发现 想看的书 Amazon 上找不到 或者排版很糟糕 如何解决 自己动手做呗 准备工作 我使用
  • UE4 UI实现改键功能

    主要内容 本文主要讲解如何在UI中实现自定义按键的功能类似于游戏中的改键操作 用到的是UE4自带的第三人称案例 因为第三人称自带了小白人和几个按键绑定就不用再手动去设置 实现步骤 1 创建两个UMG用来展示UI效果 1 创建WBP Key
  • C++链表合并

    有l1和l2两个链表 这两个链表降序排列 把l2合并到l1中 并按降序排列 同时清空l2链表 例如l1 9 8 7 6 l2 12 11 10 5 4 3 2 1 合并后l1 12 11 10 9 8 7 6 5 4 3 2 1 l2 in
  • 【Android】利用intent启动浏览器

    文章目录 一 默认浏览器 二 指定浏览器 三 选择浏览器 一 默认浏览器 需要设置Action和Date属性 构造 Uri uri Uri parse https www baidu com Intent intent new Intent
  • SCADE Suite 状态机之变量隐式赋值

    SCADE Suite 状态机之变量隐式赋值 1 变量的隐式赋值 目的 简化模型设计 Last 只要没有显示赋值 便取上一周期的数值 Default 只要没有显示赋值 便取默认设置的数值 优先级更高 设置方法 2 定义变量的Last值 1
  • LeetCode 817:链表组件(计数)

    解法一 常规解法 建图 DFS 时间复杂度O n O n 空间复杂度因为需要存储图 所以是O n 这种方法是通解 对于所有图都适用 Definition for singly linked list struct ListNode int
  • lua元表以及元方法

    知微出凡 lua元表以及元方法 lua中的变量是没有数据类型的 值有类型 类型有八种nil number boolean string function thread userdata以及table Lua 中的每个值都可以有一个 元表 这
  • 62.[GIS基础]笛卡尔坐标系

    文章目录 笛卡尔坐标系 多坐标系 坐标系的嵌套 坐标变换 坐标系转换 转载请注明原始链接 http blog csdn net a464057216 article details 54578069 后续此博客不再更新 欢迎大家搜索关注微信
  • 基于粒子群算法(PSO)优化径向基神经网络(PSO-RBF)的分类预测。matlab代码,优化参数为扩散速度,采用交叉验证。多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 读取数据 res xlsread 数据集 xlsx 分析数据 num class length unique
  • 抛去容抗角度,从电容充放电角度理解RC低通滤波器

  • 和你一起从零开始写RISC-V处理器(2)

    RISC V加法指令的实现 文章目录 RISC V加法指令的实现 上期回顾 一 正片开始 编写各个模块 pc reg模块 if模块 rom模块 if id模块 id模块 regs模块 id ex模块 ex模块 二 顶层模块搭建 三 测试文件
  • 学懂最小生成树(克鲁斯卡尔算法)

    本节 小编将带大家了解最小生成树的第二种构成算法 克鲁斯卡尔算法 Kruskal algorithm 当然 对另一种算法感兴趣的朋友可以看看之前的这篇文章 学懂最小生成树 普里姆算法 目录 一 实现原理 二 代码实现 一 实现原理 克鲁斯卡
  • 后端开发——Flask框架从入门到入坟(中)

    前言 在上一篇文章中荔枝已经梳理了Flask的基础语法 但是想要靠这些东西来写一个项目是远远不够的噢 我们还需要一个更加清晰的项目逻辑来搭建一个Flask后端项目框架 在真实的项目开发中 我们还需要了解如何搭建数据库 如何管理高效管理代码
  • leetcode刷题——栈与队列

    队列 vs 栈 栈 从头进 从头出 只有头部一个进出口 队列 从尾进 从头处 头和尾分别负责出和进 适用于配对问题 20 有效的括号 运用栈尾进头出的思想实现配对 当我们遇到一个左括号时 我们会期望在后续的遍历中 有一个相同类型的右括号将其