题目描述:
https://leetcode-cn.com/problems/basic-calculator/
实现一个基本的计算器来计算一个简单的字符串表达式的值。字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例 1: 输入: "1 + 1" 输出: 2
示例 2: 输入: " 2-1 + 2 " 输出: 3
示例 3: 输入: "(1+(4+5+2)-3)+(6+8)" 输出: 23
说明:1、你可以假设所给定的表达式都是有效的。2、请不要使用内置的库函数 eval。
题目分析:
1、由于表达式中存在括号,并且内部括号内的子表达式计算优先级大于外部,因此数据结构考虑用栈;
2、加减法运算中(A+B)+C等价于A+(B+C),但是(A-B)+C不等价于A-(B+C),因此要保证子表达式的计算顺序为从左到右;
3、数据结构选用栈,子表达式计算顺序为从左到右,因此需要的入栈顺序为从右到左,也就是需要将输入逆序;
4、不要局限于题目示例,输入的每个数字不一定是1、2这样的简单数字,还可能为123等
解题思路:
1、逆序遍历输入,数字、运算符、右括号均入栈;
2、数字的位数不一定只有一位,可能存在多位;遍历数字时,由于逆序遍历,因此得到的位数顺序为个位、十位、百位...,这样就好处理了很多;
3、遍历过程中遇到左括号,需要将栈中的元素出栈并按照运算符计算,直到栈中元素为右括号为止,然后将计算结果入栈,然后继续遍历;
4、完成1/2/3后,如果栈不为空,继续出栈并计算;
Java代码:
public class LeetCode224_calculate { private static final char LEFT = '('; private static final char RIGTH = ')'; private static final char ADD = '+'; private static final char SUB = '-'; private static final char SPACE = ' '; private static final int NUM_10 = 10; public int calculate(String s) { Stack<Object> stack = new Stack<>(); // 为了同时存储运算符和数字, 类型选择Object int number = 0; int digitCount = 0; // 逆序遍历 for (int index = s.length() - 1; index >= 0; index--) { char ch = s.charAt(index); if (ch == SPACE) { continue; } if (Character.isDigit(ch)) { // 处理多位数字的场景 number += Math.pow(NUM_10, digitCount) * (ch - '0'); digitCount++; } else { if (digitCount > 0) { stack.push(number); number = 0; digitCount = 0; } if (ch == LEFT) { // 计算子表达式的取值 int subResult = calcSub(stack); stack.pop(); // 弹出右括号 stack.push(subResult); } else { stack.push(ch); } } } // 这一步很重要, 处理最后一个单纯数字场景 if (digitCount > 0) { stack.push(number); } return calcSub(stack); } private int calcSub(Stack<Object> stack) { int result = 0; if (!stack.isEmpty()) { // 开始处理时栈不为空, 那么栈顶一定是数字 result = (int)stack.pop(); } while (!stack.isEmpty() && !((char)stack.peek() == RIGTH)) { char operate = (char)stack.pop(); if (operate == ADD) { result += (int)stack.pop(); } else if (operate == SUB) { result -= (int)stack.pop(); } } return result; } }
力扣运行结果: