An approach to implement basic calculator with RPN and stack
The article aims to provide an approach which is a combination of RPN and stack to solve Leetcode 224.
The problem is shown as follows:
"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. "
The basic calculator is actually an element in the compiler implementation. Usually, in a compiler the input string is first analyzed and converted to a sequence of valid tokens, then tokens are passed to a recursive parser to generate an abstract syntax tree. Finally we could traverse the tree for expression evaluation. Here in our problem the expression can be simplified as "expr::=expr op num". Since parentheses exist in the expression and the sub-expression inside a pair of parentheses could be regarded as an expression itself, we could borrow the idea from compiler implementation to solve the problem recursively.
An important concept I should mention is RPN. RPN is short for reverse Polish notation. It's a mathematical notation in which operands precede operator, e.g., "3 4 +". RPN is implemented is every hand-held calculator. I'll provide a detailed description in the following paragraph.
The description of the self-defined function:
- set up two stacks, one for operands and the other for operators
- scan the input string and skip empty space
- push '+' and '-' into operator stack
- return operands stack.pop if a ')' is encountered
- when encountering '(', call the function recursively, push the returned value into operands stack. if operators stack is not empty, pop out top 2 operands, pop the top operator, compute the operation result and push back to operands stack
- when a digit character is encountered, try to extend the number as long as possible until it ends, push it into the operands stack. if operators stack is not empty, pop out top 2 operands, pop the top operator, compute the operation result and push back to operands stack
Submitted code is shown below:
class Solution { private int i; public int calculate(String s) { if(s.length()==0)return 0; this.i=0; return evaluate(s); } private int evaluate(String s){ Stack<Integer> nums=new Stack<Integer>(); Stack<Character> ops=new Stack<Character>(); while(i<s.length()){ char c=s.charAt(i); switch(c){ case ' ':{ i++; } break; case '+':case '-':{ ops.push(c); i++; } break; case '(':{ i++; int num2=evaluate(s); if(!ops.empty()){ int num1=0; if(!nums.empty())num1=nums.pop(); char op=ops.pop(); if(op=='+')nums.push(num1+num2); else nums.push(num1-num2); } else nums.push(num2); } break; case ')':{ i++; return nums.pop(); } default:{ int num2=getNum(s); if(!ops.empty()){ int num1=0; if(!nums.empty())num1=nums.pop(); char op=ops.pop(); if(op=='+')nums.push(num1+num2); else nums.push(num1-num2); } else nums.push(num2); } break; } } return nums.pop(); } private int getNum(String s){ int res=0; while(i<s.length() && s.charAt(i)>='0' && s.charAt(i)<='9'){ res=10*res+s.charAt(i)-'0'; i++; } return res; } }