栈和队列(栈的应用)[二]

news2025/2/8 20:49:46

文章目录

  • 栈的应用
  • 一、栈在系统中的应用
    • 简化路径(leetcode. 71)
  • 二、扩号匹配问题
    • 有效的括号(leetcode. 20)
  • 三、字符串去重
    • 删除字符串中的所有相邻重复项(leetcode. 1047)
  • 四、逆波兰表达式问题
    • 逆波兰表达式求值(leetcode. 150)
  • 总结


栈的应用

递归的实现是栈:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。栈在计算机领域中应用是非常广泛的。像我们经常用的可视化软件例如APP、网站之类的,其底层很多功能的实现都是基础的数据结构和算法。


一、栈在系统中的应用

根据编译原理,编译器在词法分析的过程中处理括号、花括号等这个符号的逻辑,就是使用了栈这种数据结构。

简化路径(leetcode. 71)

class Solution:
    def simplifyPath(self, path: str) -> str:
        #对于路径中出现两个点或者目录名,我们则可以用一个栈来维护路径中的每一个目录名
        #当我们遇到两个点时,需要将目录切换到上一级,因此只要栈不为空,我们就弹出栈顶的目录
        #当我们遇到目录名,就把它放入栈
        #这样一来,我们只需要遍历names中的每个字符串并进行上述操作即可。
        #在所有的操作完成后,我们将从栈底到栈顶的字符串用/进行连接,再在最前面加上/表示根目录,就可以得到简化后的规范路径
        names=path.split("/")#通过分隔符对字符串路径切片,并返回分割后的字符串列表(list)
        stack=list()#创建一个空列表
        for name in names:
            if name == "..":
                if stack:
                    stack.pop()
            elif name and name!=".":
                stack.append(name)
        return "/"+"/".join(stack)#以分隔符/开头,并且列表stack元素之间以字符/连接

复杂度分析:时间复杂度O(n) ,其中n是字符串path的长度;空间复杂度O(n)我们需要O(n)的空间存储names中的所有字符串。

二、扩号匹配问题

思路:在写代码之前,我们需要先分析问题,有哪几种不匹配情况,如果不分析清楚,写出来的代码容易出问题!
大概有三种不匹配的情况:

  1. 字符串里左方向的括号多余了,所以不匹配。
    左括号多余了,是说右边没有出现与之匹配的右括号直接只出现左括号。这里只是做了个简单的举例供大家参考。
    在这里插入图片描述

  2. 括号没有多余,但是括号的类型没有匹配上。
    在这里插入图片描述

  3. 字符串里右方向的括号多余了,所以不匹配。
    右括号多余了,是说左边没有出现与之匹配的左括号直接只出现右括号。这里只是做了个简单的举例供大家参考。
    在这里插入图片描述

注意:在匹配左括号的时候,右括号先入栈,就只需比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单许多!具体来说就是,当遇到左括号时,我们是把对应的右括号入栈,而不是直接把左括号入栈,不断遍历,直到我们遍历到右方向元素遇到一个右括号,判断当前右括号元素是否与栈顶元素相等,相等就把该栈顶元素pop出去。如果我们字符串遍历完了,但是栈不为空,此时说明不匹配,左括号多了。 或者字符串还没遍历完,栈就为空了,此时说明不匹配,右括号多了。或者字符串没遍历完,元素与栈顶元素不匹配,此时说明括号类型不匹配。
类似于C++的伪代码:

stack<char> st;
if (s.size()%2!=0)
	return false;
#遍历字符串
for (i=0;i<s.size();i++){
#先处理左括号的场景
	if (s[i]=='(')
		st.push(')');
	elseif(s[i]=='{')
		st.push('}');
	elseif(s[i]=='[')
		st.push(']');
#再来处理右括号的场景
	elseif(st.empty() || st.top()!=s[i]):#第二种、三种不匹配情况处理了
		return false;
	else:
		st.pop();		
}
return st.empty();#处理第一种不匹配情况
	

有效的括号(leetcode. 20)

代码如下(示例):

# 仅使用栈,更省空间
class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        for item in s:
            if item == '(':
                stack.append(')')
            elif item == '[':
                stack.append(']')
            elif item == '{':
                stack.append('}')
            elif not stack or stack[-1] != item:
                return False
            else:
                stack.pop()
        
        return True if not stack else False

还可使用字典去做这道题

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

三、字符串去重

思路:用栈来存我们遍历过的元素,当遍历到的元素与栈顶元素相同则pop栈顶元素,消除重复项,否则就压入栈,继续遍历,最后我们从栈中弹出剩余元素,因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。
没有必要真的用一个栈去做,可以用字符串去模拟这个栈的行为。用栈顶作为字符串的尾部,栈的另一端作为字符串的头部。
在这里插入图片描述

伪代码

string result;
for(char s:S){
	if (result.empty()||s!=result.back())
		result.push_back(s);
	else:
		result.pop_back();
}
	return result;#返回字符串自然就是正确的答案,不用再反转。

时间复杂度: O(n)
空间复杂度: O(1),返回值不计空间复杂度

删除字符串中的所有相邻重复项(leetcode. 1047)

代码如下(示例):

class Solution:
    def removeDuplicates(self, s: str) -> str:
        res = list()
        for item in s:
            if res and res[-1] == item:
                res.pop()
            else:
                res.append(item)
        return "".join(res)  # 字符串拼接

时间复杂度: O(n)
空间复杂度: O(n)

四、逆波兰表达式问题

思路:逆波兰表达式就是后缀表达式RPN,比如中缀表达式(1+2)x(3+4),表示成二叉树的后续遍历。后缀表达式为(12+34+x). 遍历元素1、2入栈,再遍历+号,弹出元素1、2进行+运算,并把运算结果放入栈内,继续遍历元素加入栈,重复上述过程!整个表达式的结果就是栈里最后一个元素。
在这里插入图片描述
在这里插入图片描述
所以后缀表达式对计算机来说是非常友好的。本题也展现出计算机的思考方式,计算机可以利用栈来顺序处理,不需要考虑优先级了,也不用回退了。在1970年代和1980年代,惠普在其所有台式和手持式计算器中都使用了RPN(后缀表达式),直到2020年代仍在某些模型中使用了RPN。(参考自维基百科)

逆波兰表达式求值(leetcode. 150)

代码如下

from operator import add, sub, mul

class Solution:
    op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
    
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for token in tokens:
            if token not in {'+', '-', '*', '/'}:
                stack.append(int(token))
            else:
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(self.op_map[token](op1, op2))  # 第一个出来的在运算符后面
        return stack.pop()
        

时间复杂度: O(n)
空间复杂度: O(n)


总结

本文介绍了栈在计算机领域的应用。让我们看到了不一样的栈,原来还有这么多的应用,不可小觑!数据结构与算法的应用往往隐藏在我们看不到的地方!
(ps:近期都是关于数据结构基础知识分享,感兴趣的同学可以关注本人公众号:HEllO算法笔记

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

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

相关文章

使用腾讯手游助手作为开发测试模拟器的方案---以及部分问题的解决方案-1

目录 前言: 一.目录结构 二.注册表研究 1.HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Tencent\MobileGamePC 2.HKEY_CURRENT_USER\Software\Tencent\MobileGamePC 三.模拟器快捷启动 1.快捷启动命令: 2.启动命令如何放入桌面: 3.adb端口,目前测试均可以使用: 前言: 此…

PyTorch深度学习实战(3)——使用PyTorch构建神经网络

PyTorch深度学习实战&#xff08;3&#xff09;——使用PyTorch构建神经网络 0. 前言1. PyTorch 构建神经网络初体验1.1 使用 PyTorch 构建神经网络1.2 神经网络数据加载1.3 模型测试1.4 获取中间层的值 2. 使用 Sequential 类构建神经网络3. PyTorch 模型的保存和加载3.1 模型…

【框架源码】Spring源码解析之Bean生命周期流程

观看本文前&#xff0c;我们先思考一个问题&#xff0c;什么是Spring的bean的生命周期&#xff1f;这也是我们在面试的时候&#xff0c;面试官常问的一个问题。 在没有Spring之前&#xff0c;我们创建对象的时候&#xff0c;采用new的方式&#xff0c;当对象不在被使用的时候&…

【网络】UDP/TCP网络程序

目录 UDP网络程序 简单通信版本(UDP) 准备工作&#xff08;接口学习、分析&#xff09; 整体代码&#xff08;Server.hpp/Server.cpp/Client.hpp/Client.cpp&#xff09; 添加“婴儿版”业务逻辑 英译汉翻译 my_shell 聊天室 linux和windows通信 TCP网络程序 简单通…

AB32VG1:SDK_AB53XX_V061(3)IO口复用功能的补充资料

文章目录 1.IO口功能复用表格2.功能映射寄存器 FUNCTION03.功能映射寄存器 FUNCTION14.功能映射寄存器 FUNCTION2 AB5301A的官方数据手册很不完善&#xff0c;没有开放出来。我通过阅读源码补充了一些关于IO口功能复用寄存器的资料。 官方寄存器文档&#xff1a;《 AB32VG1_Re…

chatgpt赋能python:Python怎么截屏Windows

Python怎么截屏Windows Python是一种高级编程语言&#xff0c;具有快速开发、易于学习、可移植性强等优点&#xff0c;因此在实现Windows屏幕截图方面也是一种非常强大的工具。 什么是Windows屏幕截图&#xff1f; Windows屏幕截图是将当前屏幕或窗口的图像保存成文件或剪贴…

Android BlueToothBLE入门(二)——设备的连接和通讯(附Demo源码地址)

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为7870字&#xff0c;预计阅读12分钟 前言 接《Android BlueToothBLE入门&#xff08;一&#xff09;——低功耗蓝牙介绍》上篇&#xff0c;这篇文章主要就是来做Demo实现Android两台设备的数据通讯。 实现效…

chatgpt赋能python:Python如何快速处理数据

Python如何快速处理数据 在当今数据爆炸的时代&#xff0c;数据处理已经成为一项非常重要的任务。因此&#xff0c;如何快速、高效地处理数据就成为了每个数据科学家、数据工程师以及数据分析师的必备技能之一。而Python正是其中的佼佼者。 为什么选择Python进行数据处理 Py…

Spring事物失效的八大场景

1.方法内的自调用&#xff1a;spring事物是基于aop的&#xff0c;只要使用代理对象调用某个方法时&#xff0c;spring事物才能生效&#xff0c;而在一个方法内使用this.xxx()时。this并不是代理对象&#xff0c;所以会失效&#xff08;实际上是transaction注解失效&#xff09;…

用程序控制对文本的复制和粘贴pyperclip模块

【小白从小学Python、C、Java】 【等级考试500强双证书考研】 【Python-数据分析】 用程序控制对文本的复制和粘贴 pyperclip模块 选择题 关于下列代码说法错误的是&#xff1f; import pyperclip print(【执行】pyperclip.copy("Python 太强大了&#xff01;")) p…

读发布!设计与部署稳定的分布式系统(第2版)笔记01_生产环境的生存法则

1. 系统“应该”做什么 1.1. 添加所需特性 2. 系统“不应该”做什么 2.1. 崩溃 2.2. 停止响应 2.3. 丢失数据 2.4. 侵犯隐私 2.5. 损失金钱 2.6. 摧毁公司 2.7. “杀死”客户 3. QA部门的测试 3.1. 团队的大部分工作是想方设法地通过测试 3.2. 做了敏捷、务实和自动…

【设计模式与范式:行为型】57 | 观察者模式(下):如何实现一个异步非阻塞的EventBus框架?

上一节课中&#xff0c;我们学习了观察者模式的原理、实现、应用场景&#xff0c;重点介绍了不同应用场景下&#xff0c;几种不同的实现方式&#xff0c;包括&#xff1a;同步阻塞、异步非阻塞、进程内、进程间的实现方式。 同步阻塞是最经典的实现方式&#xff0c;主要是为了…

GreenPlum分布式集群部署实战

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

GC演变过程、三色标记法、大白话讲解G1

文章目录 GC演变过程并发垃圾回收需要解决的问题怎么确定一个垃圾?并发收集存在的问题 三色标记法CMS垃圾收集器G1垃圾收集器介绍,主要特点优点使用注意点 GC演变过程 在Java中,垃圾收集一直是一个非常重要的组成部分, 到目前为止,垃圾收集器已经有十种了, 在不停的优化. 那为…

GoogleTest之Actions的用法

目录 返回值Actions的组合验证复杂参数mock副作用改变mock对象的行为设置返回类型的默认值使用自定义函数作为Actions 通用示例 namespace mock_action { class Foo { public:virtual ~Foo() {}virtual int& GetBar() 0; // 1virtual int GetPointerValue() 0; //…

Linux CentOS7虚拟机配置静态IP并允许上网的配置方法

文章目录 前言一、开启本地电脑VMnet8二、Linux配置静态IP1. NAT模式设置2. 开启虚拟机登录root用户3. 执行命令设置静态IP4. 重启网卡① 重启网卡 (正常)② 重启网卡 (异常)③ 解决方式&#xff1a;禁用NetworkManager 5. 查看ip6. 本地电脑cmd窗口ping虚拟机7. 虚拟机ping本地…

Golang每日一练(leetDay0095) 第一个错误的版本、完全平方数

目录 278. 第一个错误的版本 First Bad Version &#x1f31f; 279. 完全平方数 Perfect Squares &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日…

springboot的数据访问和数据视图

当使用 Spring Boot 进行数据访问时&#xff0c;我们可以选择使用 MyBatis 或 JPA&#xff08;Java Persistence API&#xff09;来实现增删改查操作。下面我将分别给出使用这两种方式整合数据访问的详细步骤和示例&#xff0c;同时结合 Thymeleaf 实现数据展现。 方式一: 使用…

AI实战营:语义分割与MMSegmentation

目录 OpenMMLab图像分割算法库MMSegmentation 深度学习下的语义分割模型 全卷积网络Fully Convolutional Network 201 ​编辑 上下文信息与PSPNet模型 空洞卷积与DeepLab模型 语义分割算法总结 语义分割 前沿算法 SegFormer K-Net MaskFormer Mask2Former Seg…

PySide2 or PyQt5???该如何抉择???

1. 区别 Qt库里面有非常强大的图形界面开发库&#xff0c;但是Qt库是C语言开发的&#xff0c;PySide2、PyQt5可以让我们通过Python语言使用Qt。 但是 PySide2、PyQt5 这两者有什么区别呢&#xff1f; 可以形象地这样说&#xff1a; PySide2 是Qt的 亲儿子 &#xff0c; PyQt5 …