https://leetcode.com/problems/basic-calculator/
Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open (
and closing parentheses )
, the plus +
or minus sign -
, non-negative integers and empty spaces .
You may assume that the given expression is always valid.
Some examples:
"1 + 1" = 2 " 2-1 + 2 " = 3 "(1+(4+5+2)-3)+(6+8)" = 23
Note: Do not use the eval
built-in library function.
解题思路:
这道题虽然难度为medium,但是通过率不足20%,就知道不是那么容易的了。
首先注意的是,这道题的数字不是都是一位的,所以不能想的太简单。
于是想到把数字和加减号全部push进栈,每次计算加减法,再弹出,再看运算符。后来发现越写越复杂。最后只能参考discuss里的写法。
https://leetcode.com/discuss/39553/iterative-java-solution-with-stack
其实,只需要借助三个变量,sign代表前面的运算符,num取当前数字的值,res是累计到目前为止的运算结果。
具体的运算过程:
令当前位置的字符为cur
1.cur为数字,num = num * 10 + cur,即更新当前数值。
2. cur为+或-,更新sign,同时计算前面一个轮次的运算结果,即res = res + sign * num。同时,要将sign设置为相应的+或-。
3. cur为( ,立刻将前面已经算出的结果和记录的前一个运算符入栈,暂存。
4. cur为) ,立刻计算当前运算结果。计算完后,再弹出栈顶的两个元素,进行第二波计算。栈顶第一个一定是运算符,第二个是前面存下的数字。所以遇到右括号时,要计算两次。
5. 运算到结尾,如果num不为0,再次更新res。
public class Solution { public int calculate(String s) { int sign = 1, res = 0, num = 0; Stack<Integer> stack = new Stack<Integer>(); for(int i = 0; i < s.length(); i++) { char cur = s.charAt(i); if(cur >= '0' && cur <= '9') { num = num * 10 + (int)(cur - '0'); } else if(cur == '+') { res += sign * num; num = 0; sign = 1; } else if(cur == '-') { res += sign * num; num = 0; sign = -1; }else if(cur == '(') { stack.push(res); stack.push(sign); res = 0; sign = 1; } else if(cur == ')') { res += sign * num; res *= stack.pop(); res += stack.pop(); num = 0; } } if(num != 0) { res += sign * num; } return res; } }
这道题的思路,在上面的代码写出来后,是很清晰的。技巧就在于,同样是用stack,到底什么时候入栈,出栈。上面的解法里,stack里仅在于遇到左括号的时候,才会入栈的。