package com.freetymekiyan.algorithms.level.medium;
/**
* Implement a basic calculator to evaluate a simple expression string.
* <p>
* The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer
* division should truncate toward zero.
* <p>
* You may assume that the given expression is always valid.
* <p>
* Some examples:
* "3+2*2" = 7
* " 3/2 " = 1
* " 3+5 / 2 " = 5
* Note: Do not use the eval built-in library function.
* <p>
* Tags: String
* Similar Problems: (H) Basic Calculator, (H) Expression Add Operators
*/
public class BasicCalculator2 {
/**
* The easy way would be using a stack to store high priority results and integers.
* Then go through the stack to get final result.
* How to remove the stack? How to do it in only one-pass?
* We have only two priority levels, '*' '/' and '+' '-'.
* They can separated into two results, high level value and low level value.
* https://discuss.leetcode.com/topic/42684/explanation-for-java-o-n-time-o-1-space-solution
*/
public int calculate(String s) {
int lowVal = 0; // Result for low level operators like '+' and '-'
int highVal = 0; // Result for high level operators like '*' and '/'
int sign = 1; // 1 means '+', -1 means '-'
int priority = 0; // 0 means '+' and '-', 1 means '*', -1 means '/'
int num = 0; // Current number
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
num = num * 10 + (c - '0');
if (i == s.length() - 1 || !Character.isDigit(s.charAt(i + 1))) {
highVal = (priority == 0 ? num : (priority == 1 ? highVal * num : highVal / num));
}
} else if (c == '*' || c == '/') { // Enter high level
priority = (c == '*' ? 1 : -1); // Update priority
num = 0; // Reset current number
} else if (c == '+' || c == '-') { // Enter low level
lowVal += sign * highVal; // Accumulate high level result to low level
sign = (c == '+' ? 1 : -1); // Update sign
priority = 0; // Update priority
num = 0; // Reset current number
}
}
return lowVal + sign * highVal;
}
}