class Solution {
public int calculate(String s) {
Deque<Integer> operands = new ArrayDeque<>();
Deque<Character> operators = new ArrayDeque<>();
StringBuilder number = new StringBuilder();
int i = 0;
while (i < s.length()) {
char c = s.charAt(i);
if (c == ' ') {
i++;
continue;
}
// eg. 1 - 2 * 3 / 2
if (Character.isDigit(c)) {
number.append(c);
} else if (c == '+' || c == '-' || c == '*' || c == '/') {
if (number.length() != 0) {
operands.offerFirst(Integer.parseInt(number.toString()));
number = new StringBuilder();
}
if (operators.isEmpty()) {
operators.offerFirst(c);
} else if ((c == '*' || c == '/') && (operators.peek() == '+' || operators.peek() == '-')) {
operators.offerFirst(c);
} else if ((c == '+' || c == '-') && (operators.peek() == '*' || operators.peek() == '/')) {
// calculate all previous expressions
while (!operators.isEmpty()) {
operands.offerFirst(calculateValue(operands, operators.pollFirst()));
}
operators.offerFirst(c);
} else {
// only calculate one step
operands.offerFirst(calculateValue(operands, operators.pollFirst()));
operators.offerFirst(c);
}
}
i++;
}
if (number.length() != 0) {
operands.push(Integer.parseInt(number.toString()));
}
while (!operators.isEmpty()) {
operands.push(calculateValue(operands, operators.pollFirst()));
}
return operands.pollFirst();
}
private int calculateValue(Deque<Integer> operands, char op) {
int o2 = operands.pollFirst();
int o1 = operands.pollFirst();
if (op == '+') {
return o1 + o2;
} else if (op == '-') {
return o1 - o2;
} else if (op == '*') {
return o1 * o2;
} else {
return o1 / o2;
}
}
}