栈与计算—— 150、227、224※

news2024/11/27 10:41:29

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

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

备注:向零截断是一种取整方式,‌也称为截断取整。‌这种取整方法将一个浮点数取整为最接近但小于它的整数。‌具体来说,‌对于正数,‌向零截断会取其整数部分;‌对于负数,‌向零截断会取其绝对值的整数部分并添加负号。‌例如,‌17 / 10 = 1,‌5 / 2 = 2,‌而 -9 / 4 = -2。

解法一、双向队列模拟栈

 双向队列相关写在碎碎念里了,然后发现不用default,可以用isNumber判别

class Solution {
    public static int evalRPN(String[] tokens) {
        Deque<Integer> num = new ArrayDeque<>();
        for(String s : tokens){
            int len = num.size();
            int a,b;
            switch (s){
                case "+":
                    a = num.removeLast();//第一个
                    b = num.removeLast();//第二个
                    num.add(a+b);
                    break;
                case "-":
                    a = num.removeLast();//第一个
                    b = num.removeLast();//第二个
                    num.add(b-a);
                    break;
                case"/":
                    a = num.removeLast();//第一个
                    b = num.removeLast();//第二个
                    num.add(b/a);
                    break;
                case"*":
                    a = num.removeLast();//第一个
                    b = num.removeLast();//第二个
                    num.add(b*a);
                    break;
                default:
                    int t = Integer.parseInt(s);
                    num.add(t);
                    break;
            }
        }
        return num.pop();
    }
}

227. 基本计算器 II(中等)

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

解法一、栈

这里不用if else结构是因为需要判断那个i==n-1,如果最后一个是数字,它依旧要考虑操作符号。

大体:对于第一个数字,默认的op是‘+’,对于其他的,可以用preSign记录下来。如果是数字,则不断循环,处理num值。如果不是数字或者是最后一个数字,则考虑操作符。这里不需要考虑空格,把空格跳掉即可,空格只是干扰项。

说起来这个A&&B||C的结构也很神奇,等效于(A&&B)||C,原来&和|是有优先级区分的(没细想过这个问题)

class Solution {
    public static int calculate(String s) {
        Deque<Integer> stack = new ArrayDeque<Integer>();
        char preSign = '+';
        int num = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i) {
            if (Character.isDigit(s.charAt(i))) {
                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 '*':
                        stack.push(stack.pop() * num);
                        break;
                    default:
                        stack.push(stack.pop() / num);
                }
                preSign = s.charAt(i);
                num = 0;
            }
        }
        int ans = 0;
        while (!stack.isEmpty()) {
            ans += stack.pop();
        }
        return ans;
    }
}

 

解法二、模拟

评论区看来的~↓

用last巧妙地记录和模拟了栈顶结构。

. - 力扣(LeetCode)

class Solution {
public:
    int calculate(string s) {
        int ret = 0, last = 0;
        int value = 0;
        char op = '+';
        s += "+";
        for(auto &c:s) {
            if(isdigit(c))
                value = value * 10 + (c - '0');
            else if(c != ' ') {
                if(op == '+') {
                    ret += value;
                    last = value;
                }else if(op == '-') {
                    ret -= value;
                    last = -value;
                }else if(op == '*') {
                    ret = ret - last + value * last;
                    last = value * last;
                }else {
                    ret = ret - last + last/value;
                    last = last/value; 
                }
                op = c;
                value = 0;
            }
        }
        return ret;
    }
};

224. 基本计算器(困难) 

 

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = "1 + 1"
输出:2

示例 2:

输入:s = " 2-1 + 2 "
输出:3

示例 3:

输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

解法一、栈+模拟 

num存储数字,preOp参考227,i因为while是i++判断所以从-1开始,ops记录层数,默认一层为1,遇到(则push,遇到)则pop。因为只有加减,所以用1、-1即可

三个if(其中一个是if-else)的顺序很重要,第一个决定数字,第二个决定加减,第三个决定括号栈

易错点:①res的处理②preOp的设置③括号时ops的设置④左括号时把preOp置1

class Solution {
    public static int calculate(String s) {
        Deque<Integer> ops = new ArrayDeque<>();
        int res = 0, num = 0, preOp = 1;
        int i = -1, len = s.length();
        ops.push(1);

        //单指针循环遍历
        while (++i < len) {
            if (Character.isDigit(s.charAt(i))) {
                num = num * 10 - '0' + s.charAt(i);
            }
            if (s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == ')'|| i == len-1 ) {
                res += num * preOp * ops.element();
                if (s.charAt(i) == '+') preOp = 1;
                else preOp = -1;
                num = 0;
            }
            if (s.charAt(i) == '(') {;
                ops.push(ops.element() * preOp);
                preOp = 1;
            } else if (s.charAt(i) == ')') {
                ops.pop();
            }
        }
        return res;
    }
}

 

解法二、改进版

空格跳过,处理数字,处理符号,清晰易懂。无论哪种做法,都要记得一开始push一个1的默认值,当作全部表达式最外层套了个()处理

class Solution {
public:
    int calculate(string s) {
        stack<char> st; // 存储正负号
        int ans = 0, num = 0, op = 1;
        st.push(op);

        for (char c : s) {
            if (c == ' ') continue;
            else if (c >= '0') num = num * 10 - '0' + c;
            else {
                ans += op * num;
                num = 0;

                if (c == '+') op = st.top();
                else if (c == '-') op = -st.top();
                else if (c == '(') st.push(op); // 将括号前符号放入栈顶
                else st.pop();
            }
        }

        return ans + op * num;
    }
};

 


碎碎念:

  • 理解了这里用到的双向队列是ArrayDeque,头是0,尾/最后是末端(序号较大处)。push是从头(0)开始加,add是从尾开始加,和stack是有差别的。稍微地熟悉了element/peek之类的差别
  • 150简单使用,227稍微有些复杂(中途会错意了),224注意一下脉络和思路再写会好很多,这个需要复刷

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

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

相关文章

web前端之实现一只可爱的小杰尼乌龟、伪元素、动画

MENU 前言效果图htmlstyle 前言 代码段使用HTML和CSS创建一个“杰尼龟”的动画。 效果图 html <div class"squirtle"><div class"tail"></div><div class"body"><div class"stomach"></div><d…

了解数据库中常用存储引擎数据结构(1)

目录 引言 存储引擎和存储结构 两者的关系 存储结构 分类 1. 按数据组织方式分类 2. 按索引结构分类 3. 按存储介质分类 4. 按数据分布方式分类 5. 按数据冗余和备份分类 存储结构需要的特性 BTree 补充知识&#xff1a;Lock和Latch的区别&#xff08;存储引擎并发…

干货分享|如何使用Stable Diffusion快速打造瞬息全宇宙?

Deforum也是一款文生视频插件&#xff0c;它把提示词跃迁和运镜结合到一起&#xff0c;生成的视频让人仿佛穿越不同时空&#xff0c;因此又被称作瞬息全宇宙。本节将介绍使用Deforum生成视频的方法。 在使用Deforum时&#xff0c;由于设置参数非常多&#xff0c;初次使用时很难…

【C语言篇】编译和链接以及预处理介绍(下篇)

文章目录 前言#和###运算符##运算符 命名约定#undef命令⾏定义条件编译#if和#endif多个分支的条件编译判断是否被定义嵌套指令 头文件被包含头文件被包含的方式本地文件包含库文件的包含 嵌套文件包含 其他预处理指令 写在最后 前言 本篇接前一篇【C语言篇】编译和链接以及预处…

fvm 管理多个 flutter 版本

前言&#xff1a; flutter SDK 版本更新还是比较快的&#xff0c;新的特性带来了新的体验&#xff0c;更新频繁也是好的事情。一方面说明 flutter 社区活跃&#xff0c;另一方面 说明 flutter 进化的脚本并没有停下。这样也会带来另一个问题&#xff0c;如果多个项目 使用了不…

详解Python 66 个内置函数!附代码

大家好&#xff0c;想掌握Python编程语言&#xff0c;从零基础的小白晋升为大神&#xff1f;没问题&#xff01;接下来我们将以轻松有趣的方式&#xff0c;逐一解锁Python的66个内置函数&#xff0c;每一步都将结合实际应用场景、函数功能解析及简洁代码演示&#xff0c;带你深…

超全面!Midjourney用户手册中文版!详解模型、命令、参数与高级用法

前言 引言 大家好&#xff0c;我是包大。 最近正在上手体验目前网上很火的 AI 绘画工具 Midjourney&#xff0c;在优设和 B 站上找了很多教程来看&#xff0c;现在基本可以上手用它生成很多好玩的图片了。 这里私心推荐一下优设网的 AI 绘画专题&#xff0c;专题里已经积累了…

Docker详细讲解

2013年发布至今&#xff0c; Docker一直广受瞩目&#xff0c;被认为可能会改变软件行业。 但是&#xff0c;许多人并不清楚 Docker 到底是什么&#xff0c;要解决什么问题&#xff0c;好处又在哪里&#xff1f;今天就来详细解释&#xff0c;帮助大家理解它&#xff0c;还带有简…

【Linux操作系统】进程概念

目录 一、进程概念1.1 什么是进程 二、task_struct内容分类2.1 标识符2.2 进程状态2.2.1 进程排队2.2.2 关于进程状态的表述——运行、阻塞、挂起2.2.3 Linux中具体的进程状态2.2.4 孤儿进程 2.3 进程优先级 三、Linux的调度与切换3.1 进程切换3.2 进程调度 四、环境变量4.1 ma…

产品文档全攻略:分类、价值及创建技巧

作者 | Josh Fechter 产品文档是产品附带的资料。这些文档包含产品工作的详细信息、使用指南、免责声明以及与产品相关的其他重要详细信息。 产品文档是一个广义的术语&#xff0c;并不仅仅是为了供消费者使用。产品文档还包括供内部组织使用的产品或服务的信息。这些文档文件…

KETTLE调用http传输中文参数的问题

场景&#xff1a;检查服务器异常&#xff08;hive&#xff09;服务&#xff0c;就通过http发送一条短信到手机上&#xff0c;内容类似&#xff1a;【通知】 S T A R T D A T E h i v e 服务检测异常 {START_DATE}_hive服务检测异常 STARTD​ATEh​ive服务检测异常{DB_ID}&#…

我的点赞功能(完整分页查询步骤)和快速刷题开发

文章目录 1.我的点赞分页展示1.分页查询工具类1.PageInfo.java 需要分页查询的就继承它&#xff0c;传值的时候pageNo和pageSize可以为空2.PageResult.java 根据条件从数据库中查询信息&#xff0c;然后设置这里的四个值即可得到分页查询结果 2.sun-club-application-controlle…

记一次Nginx代理配置的奇怪经历

目录 1 背景 2 需求 3 方案 4 问题 5 解决方案 6 最后记录 7 参考文献 1 背景 最近我们在做一个能源类智能化转型的项目&#xff0c;整个项目非常大&#xff0c;下面有很多的子项目组。不同项目组之间都是独立的子系统。 客户对技术上做了统一要求&#xff0c;使用统一的…

SpringBoot 自动配置(Condition)

一.Condition Condition 是在Spring 4.0 增加的条件判断功能&#xff0c;通过这个可以功能可以实现选择性的创建 Bean 操 作。 案例&#xff1a;需求1 在 Spring 的 IOC 容器中有一个 User 的 Bean&#xff0c;现要求&#xff1a; 1. 导入Jedis坐标后&#xff0c;加载该Bean…

基于STM32开发的智能农业灌溉系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 农田自动化灌溉家庭园艺智能浇灌常见问题及解决方案 常见问题解决方案结论 1. 引言 智能农业灌溉系统通过集成多种传感器&#xff0c;实时监测土壤湿度、温度、…

​【迅为电子】RK3568驱动指南|第十七篇 串口-第196章 串口简介

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

项目视图组(基于模型)Model-Based-Qt-思维导图-学习笔记

项目视图组(基于模型)Model-Based Model-Based &#xff08;1&#xff09;List View:清单视图 QListView 继承关系&#xff1a;继承自 QAbstractItemView&#xff0c;被 QListWidget 和 QUndoView 继承 功能&#xff1a;提供模型上的列表或图标视图&#xff0c;以非分层列表…

通过连接数据库演示解耦过程

一、什么是解耦&#xff1f; 解耦就是为了降低程序之间的耦合性&#xff0c;在软件工程中&#xff0c;对象之间的耦合度就是对象之间的关联度。程序之间耦合度越高&#xff0c;程序维护起来也就越困难&#xff0c;即程序维护成本高。所以我们需要通过现有方法降低耦合性&#x…

oss学习问题记录

1.在使用oss上传文档时&#xff0c;根据返回的地址访问上传的图片&#xff0c;会报错误如下&#xff1a;This XML file does not appear to have any style information associated with it. The document tree is shown below. 在设置了上传的文档类型和代码设置读写权限之后 …

Redis的基本概念和使用

目录 一、Redis简介 1、NOSQL 2、NOSQL和关系型数据库比较 3、主流的NOSQL产品 4、什么是Redis 5、启动Redis 二、Redis基本操作 1、大概操作 三、 Redis 数据类型&#xff08;5种常用&#xff09; 1、redis 数据存储格式 2、String 3、hash 4、list 5、Set 6、…