LeetCode – Evaluate Reverse Polish Notation

Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, *, /. Each operand may be an integer or another expression. For example:

  ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
  ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6

1. Naive Approach

This problem can be solved by using a stack. We can loop through each element in the given array. When it is a number, push it to the stack. When it is an operator, pop two numbers from the stack, do the calculation, and push back the result.

Evaluate Reverse Polish Notation

The following is the code. However, this code contains compilation errors in leetcode. Why?

public class Test {
 
	public static void main(String[] args) throws IOException {
		String[] tokens = new String[] { "2", "1", "+", "3", "*" };
		System.out.println(evalRPN(tokens));
	}
 
	public static int evalRPN(String[] tokens) {
		int returnValue = 0;
		String operators = "+-*/";
 
		Stack<String> stack = new Stack<String>();
 
		for (String t : tokens) {
			if (!operators.contains(t)) { //push to stack if it is a number
				stack.push(t);
			} else {//pop numbers from stack if it is an operator
				int a = Integer.valueOf(stack.pop());
				int b = Integer.valueOf(stack.pop());
				switch (t) {
				case "+":
					stack.push(String.valueOf(a + b));
					break;
				case "-":
					stack.push(String.valueOf(b - a));
					break;
				case "*":
					stack.push(String.valueOf(a * b));
					break;
				case "/":
					stack.push(String.valueOf(b / a));
					break;
				}
			}
		}
 
		returnValue = Integer.valueOf(stack.pop());
 
		return returnValue;
	}
}

The problem is that switch string statement is only available from JDK 1.7. Leetcode apparently use a JDK version below 1.7.

2. Accepted Solution

If you want to use switch statement, you can convert the above by using the following code which use the index of a string "+-*/".

public class Solution {
    public int evalRPN(String[] tokens) {
 
        int returnValue = 0;
 
        String operators = "+-*/";
 
        Stack<String> stack = new Stack<String>();
 
        for(String t : tokens){
            if(!operators.contains(t)){
                stack.push(t);
            }else{
                int a = Integer.valueOf(stack.pop());
                int b = Integer.valueOf(stack.pop());
                int index = operators.indexOf(t);
                switch(index){
                    case 0:
                        stack.push(String.valueOf(a+b));
                        break;
                    case 1:
                        stack.push(String.valueOf(b-a));
                        break;
                    case 2:
                        stack.push(String.valueOf(a*b));
                        break;
                    case 3:
                        stack.push(String.valueOf(b/a));
                        break;
                }
            }
        }
 
        returnValue = Integer.valueOf(stack.pop());
 
        return returnValue;
 
    }
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>

  1. JeffreyT on 2013-12-21

    for the naive solution, you may want to replace “a – b” with “b – a” in case “-” of switch block.

  2. ryanlr on 2013-12-23

    Changed. Thanks!

  3. shreyas KN on 2014-3-26

    hey are we not supposed to apply the BODMAS rules here ?

  4. Henco Appel on 2014-4-16

    The hole point of RPN is that you don’t need the brackets, the order of the numbers and operators is what defines the order of the operations, so no need for brackets or BODMAS.

  5. Henco Appel on 2014-4-16

    Thought I’d point out something slightly nicer than using the index, in Java 1.6 you can switch on chars, so why not just switch on t.charAt(0) for cases ‘+’, ‘-‘, ‘*’, ‘/’. Also means that you don’t have to do a search, even though it’s only a String of 4 characters.

  6. codingfacts on 2014-6-8

    what about this case. 2*3-1

  7. Axel Hadfeg on 2014-7-9

    The problem presented above is for a reverse polish notation (or postfix notation).
    The problem you describe is in standard infix format. Postfix notation always assumes you have two operands preceding an operator. Thus your case doesn’t really apply. You could, however, make an error check for special cases that fall beyond the method’s assumptions. For example 2* would be 2 *1, or 2 *0, whatever you deem fit.

  8. Dongyon Kang on 2014-7-10

    wouldn’t b/a return an integer, which could be incorrect in cases such as “1/2” since b and a are both ints?

  9. themansitiwari on 2014-11-9

    what if we want the user to give in the input? like what if we have two digit or three digit numbers separated by comma or space?

  10. Julien Dreux on 2014-11-11

    This implementation makes wrong assumptions about the pop/push methods on arrays. Pop and push act at the end of the array, the shift and unshift methods should be used instead.

  11. sola on 2015-1-25

    I also don’t understand why the accepted solution uses Integer, it should use Double or at least Float.

  12. Salil Surendran on 2015-2-28

    What do you guys think of this solution. This is an O(n) solution

    private String findLongestPalindromicSubString(String str){

    if(str == null || str.length() == 0)
    return null;
    else if(str.length() == 1)
    return str;
    else{
    //Traverse down the string and which is each character
    //check this logic.
    int index=1;
    String longestPalindrome=null;
    while(index < str.length()/*||
    (longestPalindrome != null && str.length() – index 2 && str.charAt(index) == str.charAt(index – 2))
    currentPalindrome=readPalindrome(index – 2, index, str);

    if(currentPalindrome != null){
    if(longestPalindrome == null || currentPalindrome.length() > longestPalindrome.length())
    longestPalindrome=currentPalindrome;
    index+=currentPalindrome.length() / 2;
    }else
    index++;
    }
    return longestPalindrome;
    }
    }

  13. ryanlr on 2015-2-28

    It does not belong here, and can you put the code inside <pre> tags?

  14. sebastian on 2015-3-13

    always a and b will be an int ? dont you think that maybe b could be null ? and in this case you wil have problems with the operations.

  15. cg22165 on 2015-3-25

    Better to use a Stack of Integers. Boxing and unboxing should be more efficient than creating and garbage collecting a lot of Strings.

    Better to wrap most of the operation and data type conversions in a try-catch. The catch can simply return “Data error”, “Invalid expression”, or similar.

    The pop of a and b should be reversed. “0 1 /” is valid, but “1 0 /” is an error.

    Honey badger doesn’t care whether you use ints, doubles, bigdecimals, whatever. They are looking for a good algorithm.

  16. anonymous on 2015-3-28

    Here it is in Ruby if anyone is curious:

    def evaluate(expression)
    stack = []
    until expression.empty?
    a = expression.shift
    if (a.eql?(“+”) || a.eql?(“*”) || a.eql?(“-“) || a.eql?(“/”))
    x, y = stack.pop, stack.pop
    stack.push y.send(a, x)
    else
    stack.push a.to_i
    end
    end
    stack.first
    end
    evaluate [“4”, “13”, “5”, “/”, “+”]
    #=> 6

  17. Parag Chaudhari on 2015-3-30

    There is a bug in this code, first pop() must be a right operand and second pop() must be a left operand.

    Also, include following Edge Cases:
    1. You should check before returning that stack contains only one element.
    2. You must check divide by zero error for division operation
    3. You must handle unary operators e.g. factorial (!)
    4. Before performing any binary operation you must check whether stack has 2 operands.
    5. Before performing any unary operation you must check whether stack has 1 operand.

  18. meha on 2015-7-8

    I was evaluating the second eg. i.e [“4”, “13”, “5”, “/”, “+”] -> (4 + (13 / 5)) -> 6 and solution is 4 instead of 6, because you pop 5 and then 13 ==> which will give you 5/13 =0 and hence the expression will result in 4.

  19. Taylor Annaterre on 2015-7-24
  20. Yunxiao Zou on 2015-8-4

    naive approach works for current Leetcode Java OJ

  21. srj_michael on 2015-8-25

    It’s showing error.
    error: type stack does not take parameter.

  22. srj_michael on 2015-8-26

    Stack stack = new Stack();
    Showing error as :type stack does not take parameter

  23. Abhishek Roy on 2015-10-24

    This may be due to lowercase “s” in “string”. Try using “String” instead of “string” as shown below,
    Stack stack = new Stack();

  24. Ryan Shaw on 2015-12-16

    Python solution:

    def eval_op(land, rand, op):
    if (op == '-') return land - rand
    if (op == '+') return land + rand
    if (op == '/') return land / rand
    if (op == '*') return land * rand
    raise ValueError('unrecognized op: ' + op)

    def is_op(c):
    return c == '+' or c == '-' or c == '*' or c == '/'

    def eval(expr):
    s = []
    for c in expr:
    if not is_op(c): s.append(int(c))
    else:
    rand, land = s.pop(), s.pop()
    s.append(eval_op(land, rand, c))
    return s.pop()

  25. bimal prasad pandey on 2016-8-8

    thanx for it

  26. Greg Mueller on 2016-8-15

    Thanks Ryan, I tried this and found an error – in eval_op, you are missing the ‘:’ before each return. Also you named your main function ‘eval’, which overwrites the built-in eval function.

    I refactored your code down to this. The main difference is that I am building a string that looks like Python code and then calling eval on that string. Also, I am storing the numbers as strings, since I am not forcing the intergers to flow, or float to integer.


    def rpn(expr):
    s = []
    expr = expr.split() if type(expr) == type('') else expr
    for item in expr:
    if item.isnumeric():
    s.append(int(item))
    elif item in {'+', '-', '*', '/'}:
    intermediate_expr = ' '.join((str(s.pop()), item, str(s.pop())))
    s.append(eval(intermediate_expr))
    else:
    raise ValueError('Invalid value: ' + item)
    return s.pop()

    rpn('4 13 5 / +')
    rpn(["2", "1", "+", "3", "*"])

  27. emirpolo on 2016-10-12

    JavaScript

    function ReversePolishNotation(ain) {
    var out = [];
    ain.forEach(function(o){
    if(!isNaN(o)) {
    out.push(o);
    }
    else {
    var a = out.pop();
    var b = out.pop();
    out.push(eval(b + o + a));
    }
    });
    return out.pop();
    }

  28. LegoMushroom on 2016-11-12

    Designed the algorithm with constant space complexity O(1)! Linear time complexity O(n).

    https://discuss.leetcode.com/topic/67582/accepted-the-best-complexity-o-n-time-o-1-space-well-explained-javascript

  29. Brikesh Kumar on 2017-2-6


    public static void Main(string[] args)
    {
    //Your code goes here
    //reverse polish notation
    string[] input = new string[] {"2", "1", "+", "3", "*"};
    Stack stack = new Stack();
    int result = 0;
    for(int i = 0; i < input.Length; i++){
    int number;
    if (int.TryParse(input[i],out number)){
    stack.Push(number);
    } else{
    if (input[i] == "+"){
    var item1 = stack.Pop();
    var item2 = stack.Pop();
    result = item1 + item2;
    stack.Push(result);
    }
    if(input[i] == "*"){
    var item1 = stack.Pop();
    var item2 = stack.Pop();
    result = item1 * item2;
    stack.Push(result);
    }
    //Add more maths notations
    }
    }
    Console.WriteLine(result);

    }

  30. ANAND on 2017-3-14

    public static void main(String[] args) {
    String s[]={“2”, “1”, “+”, “3”, “*”};
    Stack stack = new Stack();
    for(int i=0;i<s.length;i++){
    if(isoperator(s[i])){
    int num1=Integer.valueOf(stack.pop());
    int num2=Integer.valueOf(stack.pop());
    switch (s[i]) {
    case "+":
    stack.push(String.valueOf(num1+num2));
    break;
    case "*":
    stack.push(String.valueOf(num1*num2));
    break;
    case "-":
    stack.push(String.valueOf(num1-num2));
    break;
    default:
    stack.push(String.valueOf(num1/num2));
    break;
    }
    }else{
    stack.push(s[i]);
    }
    }
    System.out.println(stack.pop());

    }
    public static boolean isoperator(String s){
    if(s=="*"||s=="+"||s=="/"||s=="-"){
    return true;
    }
    return false;
    }

  31. sam on 2017-4-6

    Because it is mentioned in question that “operand may be an integer or another expression”. So it is assumed to be integer.

  32. PraveenKumar Subramanian on 2017-5-16

    Division by zero is not checked.

Leave a comment

*