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.
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; } } |
Hi guys,
I created a small video explaining the stack data structure logic . Please check, any suggestions are welcome 🙂
https://www.youtube.com/watch?v=tCUhb4bRvcY
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
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.
Made a video for a JavaScript solution:
Chinese: https://www.youtube.com/watch?v=SAb1kWV7_PY
English: https://www.youtube.com/watch?v=eLf9oI0-3i8
Facebook: https://www.facebook.com/groups/2094071194216385/
// 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!");
}
}
Division by zero is not checked.
Because it is mentioned in question that “operand may be an integer or another expression”. So it is assumed to be integer.
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;
}
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);
}
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
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();
}
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", "*"])
thanx for it
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()
This may be due to lowercase “s” in “string”. Try using “String” instead of “string” as shown below,
Stack stack = new Stack();
Stack stack = new Stack();
Showing error as :type stack does not take parameter
It’s showing error.
error: type stack does not take parameter.
naive approach works for current Leetcode Java OJ
https://www.youtube.com/watch?v=-6wM2eJQWh4
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.
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.
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
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.
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.
It does not belong here, and can you put the code inside <pre> tags?
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;
}
}
I also don’t understand why the accepted solution uses Integer, it should use Double or at least Float.
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.
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?
wouldn’t b/a return an integer, which could be incorrect in cases such as “1/2” since b and a are both ints?
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.
what about this case. 2*3-1
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.
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.
hey are we not supposed to apply the BODMAS rules here ?
Changed. Thanks!
for the naive solution, you may want to replace “a – b” with “b – a” in case “-” of switch block.