Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >小鹏三面,一道 Hard 结束

小鹏三面,一道 Hard 结束

作者头像
五分钟学算法
发布于 2024-05-10 07:43:42
发布于 2024-05-10 07:43:42
52601
代码可运行
举报
文章被收录于专栏:五分钟学算法五分钟学算法
运行总次数:1
代码可运行

大家好,我是吴师兄。

一般来说,面试过程有个潜规则,如果面试官对你很满意,在算法面试环节往往会给你出一道简单题或者送分题,如果觉得不满意,则会让你手撕一道 Hard 题,让你觉得是因为这个环节表现不佳被拒。

有个网友在小鹏三面,遇到了矩形面积这道 Hard 题,没做出来,导致被拒。

底下评论大部分都是认为面试官就是不想要了,才出这样一道算法题。

有读者朋友在面试过程中手撕成功过这道算法题么?

继续今天的算法学习,来一个 Hard 的算法题:基本计算器

一、题目描述

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

示例 1:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:s = "1 + 1"
输出:2

示例 2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:s = " 2-1 + 2 "
输出:3

示例 3:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

提示:

  • 1 <= s.length <= 3 * 105
  • s 由数字、'+''-''('')'、和 ' ' 组成
  • s 表示一个有效的表达式

二、题目解析

算法考察点
  1. 栈的应用:使用栈来处理括号的计算顺序。
  2. 字符串处理:对字符串表达式进行遍历和字符的转换。
  3. 计算逻辑:根据括号的计算顺序,正确计算表达式的结果。
算法思路
  1. 使用一个栈来存储数字和括号外的运算符。
  2. 从左到右遍历字符串表达式,依次处理每个字符:
    • 如果是数字,则将其转换为整数并入栈。
    • 如果是运算符,则更新当前的符号。
    • 如果是左括号,则将当前结果和符号入栈,并初始化结果和符号。
    • 如果是右括号,则将栈顶的符号和结果出栈,计算括号内的结果,并将结果与栈顶的结果相加。
  3. 遍历完整个表达式后,栈顶元素即为计算结果。

三、参考代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 基本计算器( LeetCode 224 ):https://leetcode-cn.com/problems/basic-calculator
class Solution {
    public int calculate(String s) {

        // 使用栈来储存字符串表达式中的数字
        Stack<Integer> stack = new Stack<Integer>();

        // 为了方便计算,所有的操作都视为加法操作
        // 那么原先的减法操作就相当于是加一个负数
        // 默认都是正数
        int sign = 1;

        // 保存计算的结果
        int res = 0;

        // 获取字符串的长度,然后获取里面的每个字符
        int length = s.length();

        // 获取字符串里面的每个字符
        for (int i = 0; i < length; i++) {

            // 获取此时的字符
            char ch = s.charAt(i);

            // 如果当前字符是数字的话
            if (Character.isDigit(ch)) {

                // 那么可以通过 - '0' 这个操作把字符转换为整数
                // 相当于转换成了 ascii 码进行的数字运算
                int value = ch - '0';

                // 去查看当前字符的后一位是否存在
                // 如果操作并且后一位依旧是数字,那么就需要把后面的数字累加上来

                while (i + 1 < length && Character.isDigit(s.charAt(i + 1))){
                    
                    // i 向后移动,直到遇到非数字为止
                    i++;

                    // i 每向后移动一位,当前的值就需要乘以 10
                    // 比如 s 为 "123+456"
                    // 此时 i = 0,那么 value 为 1
                    // i = 1,那么 value 为 1 * 10 + 2 = 12
                    // i = 2,那么 value 为 12 * 10 + 3 = 123
                    value = value * 10 + s.charAt(i) - '0';

                }

                // 那么把获取到的数累加到结果 res 上
                res = res + sign * value;

              // 如果是 '+'
            } else if (ch == '+') {
                
                // 那么说明直接加一个正数
                sign = 1;

              // 如果是 '-'
            } else if (ch == '-') {

                // 那么说明加一个负数
                sign = -1;

              // 如果是 '('
            } else if (ch == '(') {
                // 根据数学计算规则,需要先计算括号里面的数字
                // 而什么时候计算呢?
                // 遇到 ) 为止
                // 所以,在遇到 ) 之前需要把之前计算好的结果存储起来再计算
                // ( ) 直接的计算规则和一开始是一样的

                // 1、先把 ( 之前的结果存放到栈中
                stack.push(res);

                // 2、重新初始化 res 为 0
                res = 0;
                // 3、把 ( 左边的操作符号存放到栈中
                // 比如如果是 5 - ( 2 + 3 ) ,那么就是把 -1 存放进去
                // 比如如果是 5 +( 2 + 3 ) ,那么就是把 1 存放进去
                stack.push(sign);

                // 4、为了方便计算,所有的操作都视为加法操作
                // 那么原先的减法操作就相当于是加一个负数
                // 默认都是正数
                sign = 1;

                // 如果是 ')'
            } else if (ch == ')') {
                
                // 那么就需要把栈中存放的元素取出来了
                // 在 ch == '(' 这个判断语句中,每次都会往栈中存放两个元素
                // 1、先存放左括号外面的结果
                // 2、再存放左括号外面的符号

                // 1、先获取栈顶元素,即左括号外面的符号,查看是 + 还是 -
                int formerSign = stack.peek();

                // 把栈顶元素弹出
                stack.pop();

                // 2、再获取栈顶元素,即左括号结果
                int formerRes = stack.peek();

                // 把栈顶元素弹出
                stack.pop();

                // 那结果就是括号外面的结果 + 括号里面的结果,至于是加正数还是负数,取决于左括号外面的符号
                res = formerRes +  formerSign * res ;

            }
        }

        // 返回计算好的结果
        return res;
    }
}

ending

我总结并录制了 100 道 LeetCode 高频算法题,涵盖了数组、链表、栈、队列、二叉树、回溯算法、动态规划等众多高频知识点,所选的题目也是非常有特征的题目,一题抵十题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
为什么很多人失业,招人却越来越难?
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
五分钟学算法
2024/04/26
1260
为什么很多人失业,招人却越来越难?
基本计算器
中缀表达式进行正常的四则运算,即按优先级高低先算括号里的再算括号外,就需要将中缀字符串转为逆波兰表达式再求解。
狼啸风云
2023/11/11
2630
基本计算器
图解java数据结构之栈(Stack),你确定不看看吗?
1)子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
慕容千语
2021/01/05
1.2K0
图解java数据结构之栈(Stack),你确定不看看吗?
[数据结构与算法] 邂逅栈
栈的英文为(stack): 又名堆栈,它是一种运算受限的线性表。限定仅在表尾(栈顶)进行插入和删除操作的线性表
时间静止不是简史
2020/07/25
4830
# 栈 栈的一个实际需求 栈的介绍 栈的应用场景 代码实现 栈实现综合计算器 # 栈的一个实际需求 请输入一个表达式 计算式:[722-5+1-5+3-3]点击计算【如下图】 请问:计算机底层是如何
用户9615083
2022/12/30
4420
栈
java数据结构和算法(二)
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
shaoshaossm
2022/12/26
3650
java数据结构和算法(二)
算法思想总结:栈
我们平时看到的 1+2*(3-4*5)+6/7 叫做中缀表达式,平时我们习惯用这个计算的原因是我们可以整体地去看到这个表达式并且清楚地知道各个运算符的优先级,但是计算机并不一定知道,因为他总是从前往后去遍历这个表达式。如上面这个例子,当按照计算机的逻辑去扫描了1+2的时候,并不敢直接去进行运算,因为可能后面存在一个优先级更高的操作符会优先进行计算。甚至有些时候还会出现括号这一种可以改变操作符优先级的符号!!所以这个时候,为了能够解决这个问题,就有了波兰表达式(前缀表达式)和逆波兰表达式(后缀表达式)。
小陈在拼命
2024/04/23
1180
算法思想总结:栈
栈的数据结构
请问: 计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们能直接看出这个算式,但是计算机怎么理解这个算式的(对计算机而言,它接收到的就是一个字符串),我们讨论的就是这个问题 -> 栈
乐心湖
2021/01/18
7230
栈的数据结构
LeetCode通过栈解题逆波兰表达式 有效的括号 栈的压入、弹出序列 最小栈 清除数字
一个表达式E的后缀形式可以如下定义: 如果E是一个变量或常量,则E的后缀式是E本身。 如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1’E2’ op,这里E1’和E2’分别为E1和E2的后缀式。 如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。 (a+b)c-(a+b)/e的后缀表达式为: (a+b)c-(a+b)/e →((a+b)c)((a+b)/e)- →((a+b)c)((a+b)e/)- →(ab+c)(ab+e/)- →ab+cab+e/- *我们将其中缀式的中每一个括号内对应的符号位置放到括号外去形成后缀表达式
如烟花般绚烂却又稍纵即逝
2024/11/26
790
LeetCode通过栈解题逆波兰表达式 有效的括号 栈的压入、弹出序列 最小栈 清除数字
表达式求值
本题主要考察对于数据结构栈的使用。我们可以定义两个栈,操作数栈和操作符号栈,依次扫描输入,处理结果。
用户7447819
2021/07/23
3830
2022: 暴杀表达式, 脚踩逆波兰的时候到了
前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。
冷环渊
2022/01/04
7170
2022: 暴杀表达式, 脚踩逆波兰的时候到了
中缀表达式转换为后缀表达式(逆波兰表达式)并对其求值
中缀表达式转后缀表达式思路: 1.初始化一个运算符栈s1和存储中间结果的List集合s2; 2.从左至右扫描中缀表达式(这里为了方便把中缀表达式字符串依次存放到数组中); 3.遇到操作数时,将其加到s2; 4.遇到运算符时,比较其与s1栈顶运算符的优先级: 4.1.若s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈 4.2.若优先级比栈顶运算符优先级高,也将运算符压入s1; 4.3.否则,将s1栈顶的运算符弹出并加到s2中,再次回到4.1与s1中新的栈顶运算符相比较 5.遇到括号时: 5.1.若是左括号“(”,则直接压入s1; 5.2.若是右括号“)”,则依次弹出s1栈顶运算符并加入s2,直到遇左括号为止,此时将这一对括号丢弃; 6.重复2-5,直到表达式最右边 7.将s1中剩余的运算符依次弹出并加入到s2 8.依次输出s2中的元素,结果即为中缀表达式对应的后缀表达式。
技术交流
2022/11/18
4300
中缀表达式转换为后缀表达式(逆波兰表达式)并对其求值
Qz学算法-数据结构篇(表达式、递归)
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素和次顶元素),并将结果入栈:重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
浅辄
2023/06/09
3250
栈(stack)的应用
版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.net/zy010101/article/details/82728726
zy010101
2019/05/25
1.3K0
数据结构之栈
后缀表达式适合计算式进行运算,但是人却不太容易写出来,尤其是表达式很长的情况下,因此在开发中,我们需要将中缀表达式转成后缀表达式。
用户11332765
2024/10/28
920
数据结构之栈
☆打卡算法☆LeetCode 224. 基本计算器 算法解析
大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。
恬静的小魔龙
2022/09/27
4720
☆打卡算法☆LeetCode 224. 基本计算器 算法解析
栈和队列篇总结
示例 1: 输入:s = "()" 输出:true 示例 2: 输入:s = "()[]{}" 输出:true 示例 3: 输入:s = "(]" 输出:false 提示:
用户11097514
2024/05/31
1010
表达式(四则运算)计算的算法
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/50394930
程序员徐公
2018/09/18
3.2K0
JS数据结构第四篇 --- 栈
  在数据结构中有一个栈结构,在内存空间中也有一个栈空间,这两个”栈“是两个不同的概念。这篇我们说的是数据结构中的栈。栈是一种特殊的线性表,特殊性体现在只能在栈顶进行操作,往栈顶添加元素,一般叫push, 入栈;从栈顶移除元素,一般叫pop, 出栈,操作如图:
tandaxia
2019/07/03
1.2K0
JS数据结构第四篇 --- 栈
算法细节系列(25):加减乘除
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/72782815
用户1147447
2019/05/26
5370
相关推荐
为什么很多人失业,招人却越来越难?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验