Given a string s
representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.
Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval()
.
Example 1:
Input: s = "1 + 1" Output: 2
Example 2:
Input: s = " 2-1 + 2 " Output: 3
Example 3:
Input: s = "(1+(4+5+2)-3)+(6+8)" Output: 23
Constraints:
1 <= s.length <= 3 * 105
s
consists of digits, '+'
, '-'
, '('
, ')'
, and ' '
.s
represents a valid expression.'+'
is not used as a unary operation (i.e., "+1"
and "+(2 + 3)"
is invalid).'-'
could be used as a unary operation (i.e., "-1"
and "-(2 + 3)"
is valid).When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to directly calculate the result of the given expression. We achieve this by processing the string character by character, keeping track of the current number and operation. It's a straightforward, step-by-step evaluation without any clever shortcuts.
Here's how the algorithm would work step-by-step:
def calculate_basic(expression):
current_number = 0
last_operation = '+'
result = 0
string_index = 0
while string_index < len(expression):
char = expression[string_index]
if char.isdigit():
current_number = (current_number * 10) + int(char)
if char in '+-*/' or string_index == len(expression) - 1:
# Perform operation when an operator or end is encountered.
if last_operation == '+':
result += current_number
elif last_operation == '-':
result -= current_number
elif last_operation == '*':
result *= current_number
elif last_operation == '/':
# Integer division as per problem description
result = int(result / current_number)
last_operation = char
current_number = 0
string_index += 1
# The final result is accumulated in the 'result' variable.
return result
To evaluate the arithmetic expression string, we avoid directly calculating from left to right due to operator precedence. Instead, we use a stack-based approach to handle parentheses and different operator priorities. The core idea is to keep track of the running result and the sign for the next number.
Here's how the algorithm would work step-by-step:
def calculate_expression(expression):
current_result = 0
current_sign = 1
stack = []
number = 0
for char in expression:
if char.isdigit():
number = number * 10 + int(char)
elif char == '+':
current_result += current_sign * number
number = 0
current_sign = 1
elif char == '-':
current_result += current_sign * number
number = 0
current_sign = -1
elif char == '(':
# Save the current state before entering parenthesis
stack.append(current_result)
stack.append(current_sign)
current_result = 0
current_sign = 1
elif char == ')':
# Evaluate the expression within the parenthesis
current_result += current_sign * number
number = 0
current_result *= stack.pop()
current_result += stack.pop()
else:
continue
return current_result + current_sign * number
Case | How to Handle |
---|---|
Empty input string | Return 0 as the evaluated value for an empty expression. |
String containing only whitespace | Remove whitespace before evaluating or return 0 if the string becomes empty after whitespace removal. |
String with leading or trailing whitespace | Trim the string before processing to avoid incorrect parsing. |
Nested parentheses | Use a stack-based approach to correctly handle the order of operations within parentheses. |
Consecutive operators (+ or -) | Combine the operators, e.g., '--' becomes '+', '+-' becomes '-'. |
Integer overflow | Use a data type that can handle larger numbers (e.g., long) and check for potential overflow during calculations, returning an error if necessary. |
Missing operand before or after operator | Return an error or invalid result, or treat it as a zero operand where appropriate. |
String contains invalid characters | Reject the string or ignore invalid characters and continue evaluating the rest, based on requirements. |