算法通过村第四关-栈黄金笔记|表达式问题

文章目录

  • 前言
    • 1. 计算器问题
    • 2. 逆波兰表达式问题
  • 总结


前言


提示:快乐的人没有过去,不快乐的人除了过去一无所有。 --理查德·弗兰纳根《深入北方的小路》

栈的进阶来了,还记得栈的使用场景吗?表达式和符号,这不就来了

1. 计算器问题

参考题目介绍:227. 基本计算器 II - 力扣(LeetCode)
在这里插入图片描述
在这里插入图片描述
计算问题在栈的运用也是非常广泛的。在乘除优先于加减计算,我们需要考虑所有的乘除运算,并将这些乘除运算后的整数放回原来对应的表达式中,随后整个表达式的值等于一系列整数加减后的运算值。

基于这样的想法,我们可以使用的们的老朋友栈了,保存这些(进行乘除运算后的)整数值。对于加减后的数字,将其直接压入栈中,对于乘除后的数字,我可以直接与栈顶元素计算,并替换栈顶元素作为计算后的结果。

具体来说,我们遍历字符串s,并用变量preSign来记录每个数字之前的运算符,对于第一个数字,其之前的运算符视为加号。每次遍历到数组的末尾时,根据preSign来决定计算方式

  • 加号:将数字压入栈中
  • 减号:将数字的相反数压入栈中
  • 乘除号:计算数字与栈顶元素,并将栈顶元素替换为计算结果。

代码实现中,读到一个运算符,或者遍历到字符串末尾,,就认为遍历到了数字末尾。处理完该数字后,更新preSign为当前遍历的字符。遍历完字符串s后,将栈中的元素累加,即为该表达式的结果。

	 /**
     * 实现计算器问题
     * @param s
     * @return
     */
    public static int calculate(String s) {
        Deque<Integer> stack = new ArrayDeque<Integer>();
        // 计算可以都看做时 +   这里是前一个符号
        Character preSign = '+';
        int num = 0;
        int n = s.length();
        for (int i = 0; i < n; i++) {
            if (Character.isDigit(s.charAt(i))) {
                // 字符转数字  考虑到大于10 的情况
                num = num * 10 + s.charAt(i) - '0';
            }
            if (!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == n - 1) {
                switch (preSign) {
                    case '+':
                        stack.push(num);
                        break;
                    case '-':
                        stack.push(-num);
                        break;
                    case '*': // 5 * 2
                        stack.push(stack.pop() * num);
                        break;
                    case '/':  // 10 / 2
                        stack.push(stack.pop() / num);
                        break;
                    default:
                        break;
                }
                // 更新前一个符号   这样就可以确定乘除优先了
                preSign = s.charAt(i);
                num = 0;
            }
        }
        int ans = 0;
        while(!stack.isEmpty()){
            ans += stack.pop();
        }
        return ans;
    }

注意:

  • perSign 指的是前一个运算符号(首次默认看作是+号)

  • 慢一次计算 就可以确保乘除优先了

2. 逆波兰表达式问题

参考题目介绍:150. 逆波兰表达式求值 - 力扣(LeetCode)
在这里插入图片描述
在这里插入图片描述
说实话这个题颇有难度,可以放在学习完二叉树再来看⭐⭐

表达式计算式编译原理,自然语言处理,文本分析等领域非常看重的问题,这里我们就挑这个题目练手,逆波兰表达式。

这道题看似困难,实则真困难呐,你要是不知道什么是表达式,完了,你不会了。这里的表达式就好比一起上小学学的(2+1)* 3这样字的,根据不同的记法,就有前缀,中缀,后缀之说,区别呢在于运算符号相对于操作数的位置,前缀就是运算符号在操作数前面,那后缀和中缀呢?你想想?

🐟聪明讲个笑话:

有一天,一只蚂蚁遇到了一只蜗牛。蚂蚁问蜗牛:“为什么我们走路的时候总是把头抬得那么高?”蜗牛回答:“因为我们的目标在地上。”

在这里插入图片描述
对应的三种表达式:

中缀表达式:( 1 + 2* 3
前缀表达式: + 1 2 * 3
后缀表达式: 1 2 + 3 *

从上面看,中缀的表达式更像是我们常见的,它作为一种通用的算数运算和逻辑公式表示,操作符以中缀形式处于操作数的中间。虽然我们的大脑很容易就可以理解这些分析最终拿到结果,但是对于计算机来说,就很头疼了,计算机在做表达式计算的时候,通常是需要将中缀表达式转换为前缀或者后缀表达式再进行求值的。前缀表达式的运算符位于两个相应操作数之前,前缀表达式又被称为前缀记法或者波兰是,而后缀表达式就是你波兰式了。

观察后我们就可以看出,根据特点将数字保存下来,遇到符号就计算。比如:1 2 + 3 * 遇到+ ,我们就好1 和 2 加起来,得到结果 3 然后在进行计算 得到结果 9 .

这样得话之不是容易一些,遇到数字就进栈,遇到运算符就取出栈中的最上面的两个元素进行计算,最后再将结果入栈。实现代码会不会简单一些:

public class EvalRPN {
    public static int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<Integer>();
        for (String token : tokens) {
            if (!Character.isDigit(token.charAt(0)) && token.length() == 1) {
                // 取出栈顶的数字
                int a = stack.pop();
                int b = stack.pop();
                // 做运算
                switch (token) {
                    case "+":   // a b +
                        stack.push(a + b);
                        break;
                    case "-": // a b -
                        stack.push(a - b);
                        break;
                    case "*": // a b *
                        stack.push(a * b);
                        break;
                    case "/": // a b /
                        stack.push(a / b);
                        break;
                    default:
                        break;
                }
            }else {
                // 直接存入栈中
                stack.push(Integer.parseInt(token));
            }
        }
        return  stack.pop();
    }

总结

提示:栈的运用,表达式策略,逆波兰。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode-中等题】437. 路径总和 III

文章目录 题目方法一&#xff1a;迭代层序 每层节点dfs 维护一个count变量 题目 方法一&#xff1a;迭代层序 每层节点dfs 维护一个count变量 思路&#xff1a; 层序遍历每一个节点遍历一个节点就对这个节点进行dfsdfs的同时&#xff0c;维护一个count变量&#xff0c;并且…

ARDUINO STM32 SSD1306

STM32F103XX系列SPI接口位置 在ARUDINO 下&#xff0c;&#xff08;不需要设置引脚功能&#xff0c;不需要开启时钟设置&#xff0c;ARDUINO已经帮我们处理了&#xff09; stm32f103c6t6 flash不足&#xff0c;不足以运行U8G2,产生错误 改用U8X8&#xff0c;后将字体改为u8x8_…

Ubuntu 22.04安装 —— Win11 22H2

目录 Ubuntu使用下载UbuntuVmware 安装图示安装步骤图示 Ubuntu使用 系统环境&#xff1a; Windows 11 22H2Vmware 17 ProUbutun 22.04.3 Server Ubuntu Server documentation | Ubuntu 下载 Ubuntu 官网下载 建议安装长期支持版本 ——> 可以选择桌面版或服务器版(仅包…

基于侏儒猫鼬算法优化的BP神经网络(预测应用) - 附代码

基于侏儒猫鼬算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于侏儒猫鼬算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.侏儒猫鼬优化BP神经网络2.1 BP神经网络参数设置2.2 侏儒猫鼬算法应用 4.测试结果&#xff1a;5…

基于JAVAEE技术的ssm校园车辆管理系统源码和论文

基于JAVAEE技术的ssm校园车辆管理系统源码和论文105 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 1.选题背景和意义 背景&#xff1a; 随着第二次工业革命后&#xff0c;内燃机的发明与完善&#xff0c;解…

原生js实现轮播图及无缝滚动

我这里主要说轮播图和无缝滚动的实现思路&#xff0c;就采用最简单的轮播图了&#xff0c;当然实现的思路有很多种&#xff0c;我这也只是其中一种。 简单轮播图的大概结构是这样的&#xff0c;中间是图片&#xff0c;二边是箭头可以用来切换图片&#xff0c;下面的小圆点也可以…

three.js(九):内置的路径合成几何体

路径合成几何体 TubeGeometry 管道LatheGeometry 车削ExtrudeGeometry 挤压 TubeGeometry 管道 TubeGeometry(path : Curve, tubularSegments : Integer, radius : Float, radialSegments : Integer, closed : Boolean) path — Curve - 一个由基类Curve继承而来的3D路径。 De…

可控生成:ControlNet原理

🤗关注公众号funNLPer体验更佳阅读🤗 论文:Adding Conditional Control to Text-to-Image Diffusion Models 代码:lllyasviel/ControlNet 简单来说ControlNet希望通过输入额外条件来控制大型图像生成模型,使得图像生成模型根据可控。 文章目录 1. 动机2. ControlNet原理…

Hadoop依赖环境配置与安装部署

目录 什么是Hadoop&#xff1f;一、Hadoop依赖环境配置1.1 设置静态IP地址1.2 重启网络1.3 再克隆两台服务器1.4 修改主机名1.5 安装JDK1.6 配置环境变量1.7 关闭防火墙1.8 服务器之间互传资料1.9 做一个host印射1.10 免密传输 二、Hadoop安装部署2.1 解压hadoop的tar包2.2 切换…

让企业主们头疼的mkp勒索病毒,究竟有何来历,勒索病毒解密

mkp勒索病毒是一种比较常见的电脑病毒&#xff0c;它会对感染的电脑进行加密&#xff0c;并要求用户支付一定的赎金才能解锁。这种病毒已经引起了全球范围内的关注&#xff0c;因为它已经造成了严重的经济损失和电脑系统崩溃。 mkp勒索病毒是一种相对较新的病毒&#xff0c;但是…

集丰照明|汽车美容店设计,装修色彩灯光搭配方法

正确处理好店面的空间设计。 店铺各个功能区设计要合理&#xff0c;衔接合理&#xff0c;这样既能提高员工的工作效率也能提高顾客的满意度。合理安排店铺的空间分配&#xff0c; 要给顾客一种舒适度&#xff0c;既不能让顾客感觉到过于拥挤&#xff0c;又不能浪费店铺的有限空…

学习高级数据结构:探索平衡树与图的高级算法

文章目录 1. 平衡树&#xff1a;维护数据的平衡与高效性1.1 AVL 树&#xff1a;严格的平衡1.2 红黑树&#xff1a;近似平衡 2. 图的高级算法&#xff1a;建模复杂关系与优化2.1 最小生成树&#xff1a;寻找最优连接方式2.2 拓扑排序&#xff1a;解决依赖关系 拓展思考 &#x1…

【Unity】URP屏幕后处理UI模糊效果实现

这里Canvas(1)设置为Overlay能渲染出指定UI高清&#xff0c;其他UI模糊&#xff0c;然而这做法非常不好&#xff0c;如果此时再打开UI 以及 关闭模糊效果 要将这些置顶UI 恢复到原本Canvas里&#xff0c;也就是要管理2套Canvas using System; using System.Collections; using…

【仿写spring之ioc篇】二、bean生命周期中的创建以及属性赋值

扫描类 这个类就不多说了&#xff0c;基本所有框架都要有这一步&#xff0c;这里主要关注我们目前要实现的方法&#xff0c;其他的具体方法可以查看源码 isComponent方法 /*** 扫描所有带有Component注解的java类&#xff0c;放入到BeanRegistry** return boolean*/public bo…

以“迅”防“汛”!5G视频快线筑牢防汛“安全堤”

近期&#xff0c;西安多地突发山洪泥石流灾害。防洪救灾刻不容缓&#xff0c;为进一步做好防汛工作&#xff0c;加强防洪调度监管&#xff0c;切实保障群众的生命财产安全&#xff0c;当地政府管理部门亟需拓展智能化技术&#xff0c;通过人防技防双保障提升防灾救灾应急处置能…

无涯教程-Android - CheckBox函数

CheckBox是可以由用户切换的on/off开关。为用户提供一组互不排斥的可选选项时,应使用复选框。 CheckBox 复选框属性 以下是与CheckBox控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。 继承自 android.widget.T…

Git企业开发控制理论和实操-从入门到深入(六)|多人协作开发

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

MTK6833_MT6833核心板_天玑700安卓5G核心板规格性能介绍

MTK6833安卓核心板采用台积电 7nm 制程的5G SoC&#xff0c;2*Cortex-A766*Cortex-A55架构&#xff0c;搭载Android12.0操作系统&#xff0c;主频最高达2.2GHz 。内置 5G 双载波聚合技术&#xff08;2CC&#xff09;及双 5G SIM 卡功能&#xff0c;实现优异的功耗表现及实时连网…

Watermark 是怎么生成和传递的?

分析&回答 Watermark 介绍 Watermark 本质是时间戳&#xff0c;与业务数据一样无差别地传递下去&#xff0c;目的是衡量事件时间的进度&#xff08;通知 Flink 触发事件时间相关的操作&#xff0c;例如窗口&#xff09;。 Watermark 是一个时间戳, 它表示小于该时间戳的…

Jenkins自动化部署-Jenkins的安装

首先我们需要安装docker 安装 yum-utils包 yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken 设置镜像地址 yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce…