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;
 
    }
}

37 thoughts on “LeetCode – Evaluate Reverse Polish Notation”

  1. can someone help me
    i wrote this program using python
    l=[]
    a=int(input())
    for i in range(a):
    b=input()
    l.append(b)
    for i in range(len(l)):
    if(l[i]==’+’):
    l[i]=l[i-2]+l[i-1]
    l[i-2:i]=[]
    elif (l[i]==’-‘):
    l[i]=l[i-2]-l[i-1]
    l[i-2:i]=[]
    elif (l[i]==’*’):
    l[i]=l[i-2]*l[i-1]
    l[i-2:i]=[]
    elif (l[i]==’/’):
    l[i]=l[i-2]/l[i-1]
    l[i-2:i]=[]
    else:
    l[i]=int(l[i])
    print(l)
    i got an error
    Traceback (most recent call last):
    File “__tester__.python3”, line 7, in
    if(l[i]==’+’):
    IndexError: list index out of range
    pls explain where i made a mistake

  2. Your comments are misleading. The second pop is left operand only. see division is (b/a) where b is second pop. if stack does not have a and b then the pop() itself will error out.

  3. // Recursive approach

    private static int reversePolishNotation(String[] arr) {
    if (arr.length == 3) {
    int a = Integer.parseInt(arr[0]);
    int b = Integer.parseInt(arr[1]);
    return calculate(a, b, arr[2]);
    } else if (arr.length > 3) {
    String[] temp = new String[arr.length – 2];
    int a = Integer.parseInt(arr[0]);
    int b = Integer.parseInt(arr[1]);
    int c = calculate(a, b, arr[2]);

    temp[0] = c + “”;

    for (int i = 3; i < arr.length; ++i) {
    temp[i – 2] = arr[i];
    }

    return reversePolishNotation(temp);
    } else {
    throw new IllegalArgumentException("wrong array input!");
    }
    }

    private static int calculate(int a, int b, String operator) {
    switch (operator) {
    case "+":
    return a + b;
    case "-":
    return a – b;
    case "*":
    return a * b;
    case "/":
    return a / b;
    default:
    throw new IllegalStateException("Oops!");
    }
    }

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

  5. 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;
    }


  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);

    }

  7. 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();
    }

  8. 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", "*"])

  9. 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()

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

  11. 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.

  12. 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.

  13. 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

  14. 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.

  15. 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.

  16. 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;
    }
    }

  17. 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.

  18. 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?

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

  20. 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.

  21. 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.

  22. 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.

Leave a Comment