An expression tree is a binary tree in which each internal node corresponds to some operator and each leaf node corresponds to some operand. We are given a string array expression of size n representing a valid expression tree.
Each element of the expression array will be in one of the following three formats:
number, which represents the value of this operand, e.g., "3", "4", "10"."+", which represents addition operator '+'."-", which represents subtraction operator '-'."*", which represents multiplication operator '*'."/", which represents division operator '/'.Please design a generic interface for the expression tree node, and write a function to evaluate the expression tree.
Example 1:
Input: expression = ["3","4","+","2","*","7","/"] Output: 6 Explanation: This represents the expression ((3+4)*(2/7)).
Example 2:
Input: expression = ["4","5","-"] Output: -1 Explanation: This represents the expression 4-5.
Constraints:
1 <= expression.length < 200expression[i] is either an integer or an operator ("+", "-", "*", or "/").[-100, 100].expression is guaranteed to be a valid expression tree.[-105, 105].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:
We're building a math problem represented as a tree, where each branch is either a number or an operation like addition. The brute force approach tries out all possible arrangements of the expression to find the final result.
Here's how the algorithm would work step-by-step:
class ExpressionTree:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def evaluate(self):
if isinstance(self.value, int):
return self.value
left_result = self.left.evaluate()
right_result = self.right.evaluate()
if self.value == '+':
return left_result + right_result
elif self.value == '-':
return left_result - right_result
elif self.value == '*':
return left_result * right_result
elif self.value == '/':
if right_result == 0:
return float('inf')
return left_result / right_result
return 0
def generate_trees(tokens):
if not tokens:
return []
trees = []
for i in range(len(tokens)):
token = tokens[i]
# If the token is an operator, we can build a tree with it as the root
if token in ['+', '-', '*', '/']:
left_subtrees = generate_trees(tokens[:i])
right_subtrees = generate_trees(tokens[i+1:])
# Combine all possible left and right subtrees to create new trees
for left_subtree in left_subtrees:
for right_subtree in right_subtrees:
tree = ExpressionTree(token, left_subtree, right_subtree)
trees.append(tree)
# If the token is a number, create a leaf node tree
else:
try:
number = int(token)
trees.append(ExpressionTree(number))
except ValueError:
pass
return trees
def evaluate_expression_brute_force(expression):
tokens = expression.split()
all_possible_trees = generate_trees(tokens)
results = []
#Evaluate all the possible trees
for tree in all_possible_trees:
results.append(tree.evaluate())
# Return all results, which is necessary given the prompt
return results
#Example usage
#expression = "3 + 2 * 5"
#results = evaluate_expression_brute_force(expression)
#print(results)The problem involves creating a tree-like structure to represent mathematical expressions and then evaluating them. The best way to tackle this is to build the tree in a specific order and then use a process called recursion to easily calculate the result.
Here's how the algorithm would work step-by-step:
class ExpressionTreeNode:
def __init__(self, value):
self.value = value
self.left_child = None
self.right_child = None
def evaluate(self):
raise NotImplementedError
class NumberNode(ExpressionTreeNode):
def __init__(self, value):
super().__init__(value)
def evaluate(self):
return self.value
class OperationNode(ExpressionTreeNode):
def __init__(self, value):
super().__init__(value)
class AdditionNode(OperationNode):
def __init__(self):
super().__init__("+")
def evaluate(self):
# Recursively evaluate children and return the sum.
return self.left_child.evaluate() + self.right_child.evaluate()
class SubtractionNode(OperationNode):
def __init__(self):
super().__init__("-")
def evaluate(self):
# Recursively evaluate children and return the difference.
return self.left_child.evaluate() - self.right_child.evaluate()
class MultiplicationNode(OperationNode):
def __init__(self):
super().__init__("*")
def evaluate(self):
return self.left_child.evaluate() * self.right_child.evaluate()
class DivisionNode(OperationNode):
def __init__(self):
super().__init__("/")
def evaluate(self):
return self.left_child.evaluate() / self.right_child.evaluate()
# Example Usage:
if __name__ == '__main__':
# Create nodes.
number_five = NumberNode(5)
number_ten = NumberNode(10)
addition_operation = AdditionNode()
addition_operation.left_child = number_five
addition_operation.right_child = number_ten
multiplication_operation = MultiplicationNode()
multiplication_operation.left_child = addition_operation
number_two = NumberNode(2)
multiplication_operation.right_child = number_two
# Evaluate the expression tree.
result = multiplication_operation.evaluate()
print(f"The result of the expression is: {result}")
subtraction_operation = SubtractionNode()
subtraction_operation.left_child = number_ten
subtraction_operation.right_child = number_five
division_operation = DivisionNode()
division_operation.left_child = number_ten
division_operation.right_child = number_two
# Recursively calculate result
division_result = division_operation.evaluate()
print(f"The result of the division is: {division_result}")
subtraction_result = subtraction_operation.evaluate()
print(f"The result of the subtraction is: {subtraction_result}")| Case | How to Handle |
|---|---|
| Null or empty expression string | Return null or throw an IllegalArgumentException, as an empty expression cannot be parsed or evaluated. |
| Expression string containing only whitespace | Return null or throw an IllegalArgumentException, as whitespace-only input is not a valid expression. |
| Expression string with invalid characters (e.g., letters, symbols other than operators) | Throw an exception indicating an invalid character was found during parsing. |
| Division by zero | Throw an ArithmeticException to prevent program crash and signal an invalid mathematical operation. |
| Integer overflow during evaluation | Use a larger data type (e.g., long) or BigInteger for intermediate calculations to prevent overflow. |
| Deeply nested expressions causing stack overflow during recursive evaluation | Convert recursive evaluation to iterative evaluation using a stack to avoid stack overflow. |
| Unbalanced parentheses in the expression string | Throw an exception indicating that the parentheses are not properly balanced during parsing. |
| Missing operands or operators in the expression string | Throw an exception during parsing, indicating a syntax error due to missing components. |