力扣每日一题:224. 基本计算器

题目:224. 基本计算器

难度: 困难

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

示例1

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

示例2

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

示例3

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

提示

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

来源:力扣(LeetCode)
链接https://leetcode-cn.com/problems/basic-calculator/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。



解题思路

  根据题意,需要我们在一堆字符串中将数字相加减得出最后结果。由提示可知,s是有效的表达式,不需要考虑各类格式输入错误。
  该题的麻烦之处在于括号,遇到括号时就不能直接相加减了。根据数学知识,计算带括号的一种方法也就是去括号法,比较适合编程实现。也就是说,每遇到一个’(‘都直接去掉它然后进行加减计算,从左往右计算,遇到’)‘则恢复之前’(‘的计算。
  因此可以利用符号函数,’+‘符号不变,’-‘符号取反。因为遇到’(’、时用去括号法可能会修改符号,而遇到’)‘又需要恢复到原来的情况,所以使用栈,遇到’(‘时将当前符号压栈,遇到’)'时出栈,保存了现场。
  在下面的代码里,sign用于符号计算,每次加减时乘上sign,而stk栈则用于遇到括号时在当前栈顶修改,弹出栈时不改变之前的符号。

解题代码

class Solution {
public:
    int calculate(string s) {
        stack<int> stk;//遇到(时将当前符号值压栈,遇到)则出栈
        stk.push(1);//默认为1
        int sign = 1;//1为+,-1为-
        int sum = 0;
        int len = s.size();
        int i = 0;

        while (i < len)
        {
            if (s[i] == ' ')
            {
                i++;
            }
            else if (s[i] == '+')
            {
                sign = stk.top();//‘+’则不需要修改符号
                i++;
            }
            else if (s[i] == '-')
            {
                sign = -stk.top();//'-'需要将当前符号取反
                i++;
            }
            else if (s[i] == '(')
            {
                stk.push(sign);//根据去符号法,将当前符号压栈,遇到‘)’出栈
                i++;
            }
            else if (s[i] == ')')
            {
                stk.pop();//一对括号外的元素符号不变
                i++;
            }
            else
            {
                long num = 0;
                while (i < len && s[i] >= '0'&& s[i] <= '9')//因为数字可能是一串,如123
                {
                    num = num * 10 + s[i] - '0';
                    i++;
                }
                sum += sign * num;
            }
        }
        return sum;
    }
};

解题感悟

  困难题,一开始没做出来,看了题解才恍然大悟。。。虽然感觉要使用栈,但是用了多个栈保存什么括号符号搞得特别复杂。
  其实不必这么复杂,去括号法+栈轻松解决问题,做了个寂寞。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值