Skip to content

Instantly share code, notes, and snippets.

@shixiaoyu
Created August 10, 2019 04:47
Show Gist options
  • Save shixiaoyu/328b5bb36978816cf5ef0534a46ee6e0 to your computer and use it in GitHub Desktop.
Save shixiaoyu/328b5bb36978816cf5ef0534a46ee6e0 to your computer and use it in GitHub Desktop.
public int calculate(String s) {
if (s == null || s.length() == 0) {
throw new IllegalArgumentException("invalid input");
}
int i = 0;
// even though leetcode does not have this use case System.out.println(ins.calculate("0-2147483648")); // -2147483648
// It can still pass with Integer, but use long for overflow case in general
Stack<Long> operands = new Stack<>();
Stack<Character> operators = new Stack<>();
StringBuilder number = new StringBuilder(); // deal with non single digit numbers
while (i < s.length()) {
char c = s.charAt(i);
if (c == ' ') {
i++;
continue;
}
if (Character.isDigit(c)) {
number.append(c);
} else if (c == '+' || c == '-' || c == '*' || c == '/') {
if (number.length() != 0) {
operands.push(Long.parseLong(number.toString()));
number = new StringBuilder();
}
// Basically based on different priority of operators
if (operators.isEmpty()) {
operators.push(c);
} else if (!operators.isEmpty() && (c == '*' || c == '/') && (operators.peek() == '+' || operators.peek() == '-')) {
// do nothing, keep pushing because */ has higher priority than +-
operators.push(c);
} else if (!operators.isEmpty() && (c == '+' || c == '-') && (operators.peek() == '*' || operators.peek() == '/')) {
// calculate all previous expressions
while (!operators.isEmpty()) {
operands.push(this.calculateValue(operands, operators.pop()));
}
operators.push(c);
} else {
// only calculating one step, for */, and +- case, one step is fine
operands.push(this.calculateValue(operands, operators.pop()));
operators.push(c);
}
}
i++;
}
if (number.length() != 0) {
operands.push(Long.parseLong(number.toString()));
}
// for "3+2*2" case that's why we need a while loop
while (!operators.isEmpty()) {
operands.push(this.calculateValue(operands, operators.pop()));
}
return (int)operands.pop().longValue(); // Since it is Long, an object can't be cast to primitive, .longValue first then cast
}
private long calculateValue(Stack<Long> operands, char op) {
long o2 = operands.pop();
long o1 = operands.pop();
if (op == '+') {
return o1 + o2;
} else if (op == '-') {
return o1 - o2;
} else if (op == '*') {
return o1 * o2;
} else if (op == '/') {
return o1 / o2;
} else {
throw new IllegalArgumentException("invalid op!");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment