Skip to content

Instantly share code, notes, and snippets.

@junjiah
Last active August 29, 2015 14:24
Show Gist options
  • Save junjiah/7dcd4835722b2c828b76 to your computer and use it in GitHub Desktop.
Save junjiah/7dcd4835722b2c828b76 to your computer and use it in GitHub Desktop.
solved 'Basic Calculator II' on leetcode https://leetcode.com/problems/basic-calculator-ii/
/**
* Inspired from https://leetcode.com/discuss/42643/my-16-ms-no-stack-one-pass-short-c-solution
**/
class Solution {
public:
// Regard expression series of *,/ as blocks,
// and try to 'inline' them as a single number.
int calculate(string s) {
// Expression result of current 'block'.
long curr_res = 0;
// Final result.
long res = 0;
// Regard the first number x as 0 + x.
char prev_op = '+';
int i = 0;
const int len = s.length();
while (i < len) {
if (s[i] == ' ') {
++i;
continue;
}
// If is a number, parse it.
if (isdigit(s[i])) {
int parsing_num = 0;
do {
parsing_num = parsing_num * 10 + (s[i] - '0');
++i;
} while (isdigit(s[i]));
// 'Inline' operation result to current number.
switch (prev_op) {
case '*':
curr_res *= parsing_num;
break;
case '/':
curr_res /= parsing_num;
break;
case '+':
curr_res += parsing_num;
break;
case '-':
curr_res -= parsing_num;
}
} else {
char curr_op = s[i];
if (curr_op == '+' || curr_op == '-') {
// Safe to accumulate the result of current block expression.
res += curr_res;
curr_res = 0;
}
prev_op = curr_op;
++i;
}
}
res += curr_res;
return res;
}
};
class Solution {
public:
int calculate(string s) {
stack<long> operand_stack;
stack<char> op_stack;
long curr_num = 0;
int prev_op_precedence = -1;
for (char ch : s) {
if (ch == ' ') {
continue;
}
else if (ch >= '0' && ch <= '9') {
curr_num = curr_num * 10 + (ch - '0');
continue;
} else {
// Number parsed.
operand_stack.push(curr_num);
curr_num = 0;
}
// Calculate precedence: '*' or '/' -> 1,
// '+' or '-' -> 0.
int op_precedence = ch == '*' || ch == '/';
if (op_precedence <= prev_op_precedence) {
// Safe to calculate expressions in current stacks.
consumeStacks(operand_stack, op_stack, op_precedence);
}
op_stack.push(ch);
prev_op_precedence = op_precedence;
}
// Process the final number.
operand_stack.push(curr_num);
if (!op_stack.empty()) {
consumeStacks(operand_stack, op_stack, 0);
}
return operand_stack.top();
}
private:
long eval(int operand1, int operand2, char op) {
long res;
switch (op) {
case '+':
res = operand2 + operand1;
break;
case '-':
res = operand2 - operand1;
break;
case '*':
res = operand2 * operand1;
break;
case '/':
res = operand2 / operand1;
}
return res;
}
template<class T>
inline static T getTopAndPop(stack<T> &st) {
T res = st.top();
st.pop();
return res;
}
void consumeStacks(stack<long> &operand_stack,
stack<char> &op_stack, int op_precedence) {
long operand1, operand2, op_stack_top_precedence;
char op;
do {
operand1 = getTopAndPop(operand_stack);
operand2 = getTopAndPop(operand_stack);
op = getTopAndPop(op_stack);
// Eval and push to the operand stack
operand_stack.push(eval(operand1, operand2, op));
// Update prev precedence.
op_stack_top_precedence =
op_stack.empty() ?
-1 : (op_stack.top() == '*' || op_stack.top() == '/');
} while (op_precedence <= op_stack_top_precedence);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment