[LeetCode] 772. Basic Calculator III
Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, '+'
, '-'
, '*'
, '/'
operators, and open '('
and closing parentheses ')'
. The integer division should truncate toward zero.
You may assume that the given expression is always valid. All intermediate results will be in the range of [-231, 231 - 1]
.
Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval()
.
Example 1:
Input: s = "1+1" Output: 2
Example 2:
Input: s = "6-4/2" Output: 4
Example 3:
Input: s = "2*(5+5*2)/3+(6/2+8)" Output: 21
Constraints:
1 <= s <= 104
s
consists of digits,'+'
,'-'
,'*'
,'/'
,'('
, and')'
.s
is a valid expression.
基本计算器 III。
题意是前两个版本的综合,既要处理四则运算,又要处理带括号的情形。
思路是递归 + 栈。我参考了这个帖子。为什么要用栈,是为了在遇到符号的时候,你要计算局部结果,这个是和版本一和版本二类似的地方;为什么要用递归,是因为你不知道到底有多少层括号的嵌套,而且因为括号部分计算的优先级是比乘法和除法高的,必须先计算好括号内的内容,才能把括号内的局部结果拿出来参与别的运算。
这里我们一开始需要一个全局变量 index 来帮助 track 到底走到 input 字符串的什么位置上了。然后我们开始遍历 input,这里我们还是像前两个版本一样创建两个变量,sign 表示符号,num 表示遇到的数字,这里都很正常。当遇到一个左括号的时候,括号内的局部结果 num 就需要用递归来计算了。
时间O(n!) - worst case
空间O(n)
Java实现
1 class Solution { 2 public int calculate(String s) { 3 Deque<Integer> stack = new ArrayDeque<>(); 4 int num = 0; 5 char sign = '+'; 6 for (int i = 0; i < s.length(); i++) { 7 char c = s.charAt(i); 8 if (Character.isDigit(c)) { 9 num = num * 10 + c - '0'; 10 } 11 12 if (c == '(') { 13 // 左括号的数量 14 int left = 1; 15 int j = i + 1; 16 // 有可能遇到多个嵌套的括号 17 // 判断到底哪个右括号是当前左括号的配对是通过计算左右括号的数量 18 // 跳出while循环就说明左右括号的数量能抵消,j - 1位置上的那个右括号就是与当前左括号配对的那个右括号 19 while (left > 0) { 20 if (s.charAt(j) == '(') { 21 left++; 22 } else if (s.charAt(j) == ')') { 23 left--; 24 } 25 j++; 26 } 27 num = calculate(s.substring(i + 1, j)); 28 // i = j - 1的意思是当此轮for循环跑完,i会因为for循环的关系,自己走到j的位置上,所以这里要定义成j - 1 29 i = j - 1; 30 } 31 32 if (c != ' ' && !Character.isDigit(c) || i == s.length() - 1) { 33 if (sign == '+') { 34 stack.push(num); 35 } else if (sign == '-') { 36 stack.push(-num); 37 } else if (sign == '*') { 38 stack.push(stack.pop() * num); 39 } else if (sign == '/') { 40 stack.push(stack.pop() / num); 41 } 42 sign = c; 43 num = 0; 44 } 45 } 46 int sum = 0; 47 while (!stack.isEmpty()) { 48 sum += stack.pop(); 49 } 50 return sum; 51 } 52 }
相关题目