1628. Design an Expression Tree With Evaluate Function 🔒
Problem Description
You need to build a binary expression tree from a postfix expression and evaluate it.
Input: An array of strings representing a postfix expression, where:
- Numbers (operands) are represented as strings like "4", "5", "7", "2"
- Operators are represented as "+", "-", "*", "/"
Output: A binary expression tree (implemented using the Node interface) that represents the given postfix expression.
Example:
For the infix expression 4*(5-(7+2))
, the postfix representation is ["4","5","7","2","+","-","*"]
. You need to construct a tree that evaluates to the correct result.
Binary Expression Tree Structure:
- Leaf nodes (0 children) contain operands (numbers)
- Internal nodes (2 children) contain operators
- Each operator node has exactly two children (left and right subtrees)
Key Requirements:
- Implement the
Node
interface with anevaluate()
method that computes the value of the tree - Create a
TreeBuilder
class with abuildTree()
method that constructs the tree from the postfix expression - The tree should correctly evaluate mathematical expressions using standard operator precedence
Postfix Notation: In postfix notation, operators come after their operands. For example:
- Infix:
5 + 7
becomes Postfix:["5", "7", "+"]
- Infix:
4 * (5 - (7 + 2))
becomes Postfix:["4", "5", "7", "2", "+", "-", "*"]
Constraints:
- All operations are valid (no division by zero)
- No subtree will evaluate to a value exceeding
10^9
in absolute value - The expression will only contain the four basic arithmetic operators:
+
,-
,*
,/
Follow-up Challenge: Design your solution to be modular enough to support additional operators without modifying the existing evaluate()
implementation.
Intuition
The key insight for solving this problem comes from understanding how postfix expressions are evaluated. When we manually evaluate a postfix expression, we scan from left to right and:
- When we see a number, we remember it for later use
- When we see an operator, we immediately apply it to the most recent two numbers we've seen
This naturally suggests using a stack data structure. Think about it: we need to store numbers as we encounter them, and when we hit an operator, we need the two most recently stored numbers - this is exactly what a stack gives us with its Last-In-First-Out (LIFO) property.
But here's the clever part: instead of just storing numbers on the stack and computing values, we can store tree nodes instead. This way, we're building the tree structure as we process the expression.
The construction process mirrors the evaluation process:
- When we encounter a number (operand), we create a leaf node and push it onto the stack
- When we encounter an operator, we:
- Pop two nodes from the stack (these become the children)
- Create a new node with the operator as its value
- Make the popped nodes its children (careful with the order - the first popped becomes the right child, the second becomes the left child)
- Push this new subtree back onto the stack
Why does this work? Because in postfix notation, an operator always appears immediately after all of its operands have been fully specified. By the time we see an operator, we've already built the complete subtrees for its operands, and they're sitting on top of the stack waiting to be combined.
At the end of processing all tokens, the stack contains exactly one element - the root of our complete expression tree. This root represents the entire expression, with all operations properly structured according to the original postfix notation.
The beauty of this approach is that it builds the tree in a single pass through the postfix expression, with each token being processed exactly once, giving us an efficient O(n)
solution.
Learn more about Stack, Tree, Math and Binary Tree patterns.
Solution Approach
The implementation uses a stack-based approach to construct the binary expression tree from the postfix notation. Let's walk through the key components:
Node Implementation
First, we implement the MyNode
class that extends the abstract Node
interface:
class MyNode(Node):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
Each node stores:
val
: The value (either a number as a string or an operator)left
: Reference to the left childright
: Reference to the right child
The evaluate()
method recursively computes the value:
- If the node contains a digit (leaf node), it returns the integer value
- If the node contains an operator (internal node), it:
- Recursively evaluates the left and right subtrees
- Applies the operator to the results
Tree Construction Algorithm
The buildTree
method implements the core algorithm:
def buildTree(self, postfix: List[str]) -> 'Node':
stk = []
for s in postfix:
node = MyNode(s)
if not s.isdigit():
node.right = stk.pop()
node.left = stk.pop()
stk.append(node)
return stk[-1]
Step-by-step process:
-
Initialize an empty stack
stk
-
Iterate through each token
s
in the postfix expression:- Create a new node with value
s
- Create a new node with value
-
Check if the token is an operator (not a digit):
- If it's an operator:
- Pop the top node from stack → becomes the right child
- Pop the next node from stack → becomes the left child
- Note: The order matters! The first popped node is the right child because of how postfix notation works
- If it's an operator:
-
Push the current node onto the stack:
- If it was a number, we push a leaf node
- If it was an operator, we push a subtree with the operator as root
-
After processing all tokens, the stack contains exactly one element - the root of the complete expression tree
Example Walkthrough
For postfix expression ["4", "5", "7", "2", "+", "-", "*"]
:
- Process "4": Push leaf node(4) → Stack: [4]
- Process "5": Push leaf node(5) → Stack: [4, 5]
- Process "7": Push leaf node(7) → Stack: [4, 5, 7]
- Process "2": Push leaf node(2) → Stack: [4, 5, 7, 2]
- Process "+": Pop 2 and 7, create node(+) with children → Stack: [4, 5, (7+2)]
- Process "-": Pop (7+2) and 5, create node(-) with children → Stack: [4, (5-(7+2))]
- Process "": Pop (5-(7+2)) and 4, create node() with children → Stack: [(4*(5-(7+2)))]
The final stack contains the root of the tree representing 4*(5-(7+2))
.
Time and Space Complexity
- Time Complexity:
O(n)
where n is the number of tokens. Each token is processed exactly once. - Space Complexity:
O(n)
for the stack and the resulting tree structure.
The solution elegantly leverages the properties of postfix notation where operators always appear after their operands, making it perfect for stack-based processing.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a simple example with the postfix expression ["3", "4", "+", "2", "*"]
, which represents the infix expression (3 + 4) * 2
.
Step-by-step construction:
Initial state: Stack = []
Step 1: Process "3"
- Create a leaf node with value "3"
- It's a digit, so no children needed
- Push to stack
- Stack = [Node(3)]
Step 2: Process "4"
- Create a leaf node with value "4"
- It's a digit, so no children needed
- Push to stack
- Stack = [Node(3), Node(4)]
Step 3: Process "+"
- Create a node with value "+"
- It's an operator, so we need children:
- Pop Node(4) → becomes right child
- Pop Node(3) → becomes left child
- Create the subtree:
+ / \ 3 4
- Push this subtree to stack
- Stack = [Node(+) with children 3 and 4]
Step 4: Process "2"
- Create a leaf node with value "2"
- It's a digit, so no children needed
- Push to stack
- Stack = [Node(+) with children 3 and 4, Node(2)]
Step 5: Process "*"
- Create a node with value "*"
- It's an operator, so we need children:
- Pop Node(2) → becomes right child
- Pop Node(+) with its subtree → becomes left child
- Create the final tree:
* / \ + 2 / \ 3 4
- Push this tree to stack
- Stack = [Node(*) as root of complete tree]
Final Result: The stack contains one element - the root of our expression tree.
Evaluation:
When we call evaluate()
on the root:
- Root is "*", so evaluate left and right children
- Left child is "+", so evaluate its children: 3 + 4 = 7
- Right child is "2", return 2
- Apply multiplication: 7 * 2 = 14
The tree correctly evaluates to 14, which matches (3 + 4) * 2 = 14.
Solution Implementation
1from abc import ABC, abstractmethod
2from typing import List, Optional
3
4"""
5This is the interface for the expression tree Node.
6You should not remove it, and you can define some classes to implement it.
7"""
8
9
10class Node(ABC):
11 @abstractmethod
12 def evaluate(self) -> int:
13 """Abstract method to evaluate the expression tree."""
14 pass
15
16
17class ExpressionNode(Node):
18 """
19 Concrete implementation of Node for expression tree.
20 Can represent either an operand (number) or an operator (+, -, *, /).
21 """
22
23 def __init__(self, value: str) -> None:
24 """
25 Initialize a node with a value (either a number or an operator).
26
27 Args:
28 value: String representing either a digit or an operator
29 """
30 self.value: str = value
31 self.left: Optional[Node] = None
32 self.right: Optional[Node] = None
33
34 def evaluate(self) -> int:
35 """
36 Recursively evaluate the expression tree.
37
38 Returns:
39 Integer result of the expression evaluation
40 """
41 # If the node contains a digit, return its integer value
42 if self.value.isdigit():
43 return int(self.value)
44
45 # Recursively evaluate left and right subtrees
46 left_result: int = self.left.evaluate()
47 right_result: int = self.right.evaluate()
48
49 # Apply the operator to the operands
50 if self.value == '+':
51 return left_result + right_result
52 elif self.value == '-':
53 return left_result - right_result
54 elif self.value == '*':
55 return left_result * right_result
56 elif self.value == '/':
57 # Use integer division (floor division)
58 return left_result // right_result
59
60
61"""
62This is the TreeBuilder class.
63You can treat it as the driver code that takes the postfix input
64and returns the expression tree representing it as a Node.
65"""
66
67
68class TreeBuilder:
69 """
70 Builder class to construct an expression tree from postfix notation.
71 """
72
73 def buildTree(self, postfix: List[str]) -> Node:
74 """
75 Build an expression tree from postfix notation.
76
77 Algorithm:
78 1. Iterate through each token in the postfix expression
79 2. For operands: create a leaf node and push to stack
80 3. For operators: pop two nodes, make them children, push result
81
82 Args:
83 postfix: List of strings representing postfix expression
84
85 Returns:
86 Root node of the constructed expression tree
87 """
88 # Stack to store nodes during tree construction
89 stack: List[Node] = []
90
91 for token in postfix:
92 # Create a new node for the current token
93 node = ExpressionNode(token)
94
95 # If token is an operator, pop two operands and set as children
96 if not token.isdigit():
97 # Right child is popped first (stack is LIFO)
98 node.right = stack.pop()
99 # Left child is popped second
100 node.left = stack.pop()
101
102 # Push the node (either leaf or subtree) onto the stack
103 stack.append(node)
104
105 # The final element in the stack is the root of the expression tree
106 return stack[-1]
107
108
109"""
110Your TreeBuilder object will be instantiated and called as such:
111obj = TreeBuilder()
112expTree = obj.buildTree(postfix)
113ans = expTree.evaluate()
114"""
115
1/**
2 * This is the interface for the expression tree Node.
3 * You should not remove it, and you can define some classes to implement it.
4 */
5abstract class Node {
6 public abstract int evaluate();
7
8 // Fields for storing node value and children
9 protected String val;
10 protected Node left;
11 protected Node right;
12}
13
14/**
15 * Concrete implementation of Node for expression tree
16 */
17class MyNode extends Node {
18
19 /**
20 * Constructor to create a node with given value
21 * @param val The value of the node (operator or operand)
22 */
23 public MyNode(String val) {
24 this.val = val;
25 }
26
27 /**
28 * Evaluates the expression tree rooted at this node
29 * @return The integer result of evaluating the expression
30 */
31 public int evaluate() {
32 // Base case: if node is a number, return its integer value
33 if (isNumeric()) {
34 return Integer.parseInt(val);
35 }
36
37 // Recursive case: evaluate left and right subtrees
38 int leftValue = left.evaluate();
39 int rightValue = right.evaluate();
40
41 // Apply the operator to the operands
42 if (Objects.equals(val, "+")) {
43 return leftValue + rightValue;
44 }
45 if (Objects.equals(val, "-")) {
46 return leftValue - rightValue;
47 }
48 if (Objects.equals(val, "*")) {
49 return leftValue * rightValue;
50 }
51 if (Objects.equals(val, "/")) {
52 return leftValue / rightValue;
53 }
54
55 // Default return (should not reach here with valid input)
56 return 0;
57 }
58
59 /**
60 * Checks if the node value represents a numeric operand
61 * @return true if the value is numeric, false if it's an operator
62 */
63 public boolean isNumeric() {
64 // Check each character to determine if the string is a number
65 for (char c : val.toCharArray()) {
66 if (!Character.isDigit(c)) {
67 return false;
68 }
69 }
70 return true;
71 }
72}
73
74/**
75 * This is the TreeBuilder class.
76 * You can treat it as the driver code that takes the postfix input
77 * and returns the expression tree representing it as a Node.
78 */
79class TreeBuilder {
80
81 /**
82 * Builds an expression tree from a postfix expression
83 * @param postfix Array of strings representing the postfix expression
84 * @return Root node of the constructed expression tree
85 */
86 Node buildTree(String[] postfix) {
87 // Stack to store nodes during tree construction
88 Deque<MyNode> stack = new ArrayDeque<>();
89
90 // Process each token in the postfix expression
91 for (String token : postfix) {
92 MyNode node = new MyNode(token);
93
94 // If token is an operator, pop two operands and set as children
95 if (!node.isNumeric()) {
96 node.right = stack.pop(); // Right child is popped first
97 node.left = stack.pop(); // Left child is popped second
98 }
99
100 // Push the current node onto the stack
101 stack.push(node);
102 }
103
104 // The final node on the stack is the root of the expression tree
105 return stack.peek();
106 }
107}
108
109/**
110 * Your TreeBuilder object will be instantiated and called as such:
111 * TreeBuilder obj = new TreeBuilder();
112 * Node expTree = obj.buildTree(postfix);
113 * int ans = expTree.evaluate();
114 */
115
1/**
2 * This is the interface for the expression tree Node.
3 * You should not remove it, and you can define some classes to implement it.
4 */
5class Node {
6public:
7 virtual ~Node() {};
8 virtual int evaluate() const = 0;
9
10protected:
11 // define your fields here
12 std::string value;
13 Node* left;
14 Node* right;
15};
16
17/**
18 * Implementation of Node interface for expression tree nodes
19 * Supports both leaf nodes (operands) and internal nodes (operators)
20 */
21class ExpressionNode : public Node {
22public:
23 // Constructor for leaf nodes (operands)
24 ExpressionNode(const std::string& val) : left(nullptr), right(nullptr) {
25 this->value = val;
26 }
27
28 // Constructor for internal nodes (operators)
29 ExpressionNode(const std::string& val, Node* leftChild, Node* rightChild) {
30 this->value = val;
31 this->left = leftChild;
32 this->right = rightChild;
33 }
34
35 /**
36 * Recursively evaluates the expression tree
37 * @return The integer result of the expression
38 */
39 int evaluate() const override {
40 // Check if current node is a leaf (operand)
41 if (!isOperator(value)) {
42 return std::stoi(value);
43 }
44
45 // Recursively evaluate left and right subtrees
46 int leftValue = left->evaluate();
47 int rightValue = right->evaluate();
48
49 // Apply the operator to the operands
50 if (value == "+") {
51 return leftValue + rightValue;
52 } else if (value == "-") {
53 return leftValue - rightValue;
54 } else if (value == "*") {
55 return leftValue * rightValue;
56 } else if (value == "/") {
57 return leftValue / rightValue;
58 }
59
60 return 0; // Should never reach here for valid input
61 }
62
63private:
64 // Helper function to check if a string is an operator
65 bool isOperator(const std::string& s) const {
66 return s == "+" || s == "-" || s == "*" || s == "/";
67 }
68};
69
70/**
71 * This is the TreeBuilder class.
72 * You can treat it as the driver code that takes the postfix input
73 * and returns the expression tree representing it as a Node.
74 */
75class TreeBuilder {
76public:
77 /**
78 * Builds an expression tree from postfix notation
79 * @param postfix Vector of strings representing the postfix expression
80 * @return Root node of the constructed expression tree
81 */
82 Node* buildTree(std::vector<std::string>& postfix) {
83 std::stack<ExpressionNode*> nodeStack;
84
85 // Process each token in the postfix expression
86 for (const auto& token : postfix) {
87 ExpressionNode* currentNode;
88
89 if (isOperator(token)) {
90 // Pop two operands for the operator
91 ExpressionNode* rightOperand = nodeStack.top();
92 nodeStack.pop();
93 ExpressionNode* leftOperand = nodeStack.top();
94 nodeStack.pop();
95
96 // Create operator node with operands as children
97 currentNode = new ExpressionNode(token, leftOperand, rightOperand);
98 } else {
99 // Create leaf node for operand
100 currentNode = new ExpressionNode(token);
101 }
102
103 // Push the newly created node onto the stack
104 nodeStack.push(currentNode);
105 }
106
107 // The final node on the stack is the root of the expression tree
108 return nodeStack.top();
109 }
110
111private:
112 // Helper function to check if a string is an operator
113 bool isOperator(const std::string& s) const {
114 return s == "+" || s == "-" || s == "*" || s == "/";
115 }
116};
117
118/**
119 * Your TreeBuilder object will be instantiated and called as such:
120 * TreeBuilder* obj = new TreeBuilder();
121 * Node* expTree = obj->buildTree(postfix);
122 * int ans = expTree->evaluate();
123 */
124
1/**
2 * Interface for the expression tree Node
3 */
4interface Node {
5 evaluate(): number;
6 value?: string;
7 left?: Node | null;
8 right?: Node | null;
9}
10
11/**
12 * Implementation of Node interface for expression tree nodes
13 * Supports both leaf nodes (operands) and internal nodes (operators)
14 */
15class ExpressionNode implements Node {
16 value: string;
17 left: Node | null;
18 right: Node | null;
19
20 /**
21 * Constructor for both leaf nodes (operands) and internal nodes (operators)
22 * @param val - The value of the node (operator or operand)
23 * @param leftChild - Left child node (null for leaf nodes)
24 * @param rightChild - Right child node (null for leaf nodes)
25 */
26 constructor(val: string, leftChild: Node | null = null, rightChild: Node | null = null) {
27 this.value = val;
28 this.left = leftChild;
29 this.right = rightChild;
30 }
31
32 /**
33 * Recursively evaluates the expression tree
34 * @returns The integer result of the expression
35 */
36 evaluate(): number {
37 // Check if current node is a leaf (operand)
38 if (!this.isOperator(this.value)) {
39 return parseInt(this.value);
40 }
41
42 // Recursively evaluate left and right subtrees
43 const leftValue = this.left!.evaluate();
44 const rightValue = this.right!.evaluate();
45
46 // Apply the operator to the operands
47 switch (this.value) {
48 case "+":
49 return leftValue + rightValue;
50 case "-":
51 return leftValue - rightValue;
52 case "*":
53 return leftValue * rightValue;
54 case "/":
55 // Integer division (truncate towards zero)
56 return Math.trunc(leftValue / rightValue);
57 default:
58 return 0; // Should never reach here for valid input
59 }
60 }
61
62 /**
63 * Helper function to check if a string is an operator
64 * @param s - String to check
65 * @returns True if the string is an operator, false otherwise
66 */
67 private isOperator(s: string): boolean {
68 return s === "+" || s === "-" || s === "*" || s === "/";
69 }
70}
71
72/**
73 * TreeBuilder class that constructs expression trees from postfix notation
74 */
75class TreeBuilder {
76 /**
77 * Builds an expression tree from postfix notation
78 * @param postfix - Array of strings representing the postfix expression
79 * @returns Root node of the constructed expression tree
80 */
81 buildTree(postfix: string[]): Node {
82 const nodeStack: ExpressionNode[] = [];
83
84 // Process each token in the postfix expression
85 for (const token of postfix) {
86 let currentNode: ExpressionNode;
87
88 if (this.isOperator(token)) {
89 // Pop two operands for the operator
90 const rightOperand = nodeStack.pop()!;
91 const leftOperand = nodeStack.pop()!;
92
93 // Create operator node with operands as children
94 currentNode = new ExpressionNode(token, leftOperand, rightOperand);
95 } else {
96 // Create leaf node for operand
97 currentNode = new ExpressionNode(token);
98 }
99
100 // Push the newly created node onto the stack
101 nodeStack.push(currentNode);
102 }
103
104 // The final node on the stack is the root of the expression tree
105 return nodeStack[nodeStack.length - 1];
106 }
107
108 /**
109 * Helper function to check if a string is an operator
110 * @param s - String to check
111 * @returns True if the string is an operator, false otherwise
112 */
113 private isOperator(s: string): boolean {
114 return s === "+" || s === "-" || s === "*" || s === "/";
115 }
116}
117
118/**
119 * Usage example:
120 * const obj = new TreeBuilder();
121 * const expTree = obj.buildTree(postfix);
122 * const ans = expTree.evaluate();
123 */
124
Time and Space Complexity
Time Complexity: O(n)
where n
is the length of the postfix expression array.
- The
buildTree
method iterates through each element in the postfix array exactly once, performingO(1)
operations for each element (creating a node, popping from stack, appending to stack). This results inO(n)
time for building the tree. - The
evaluate
method performs a post-order traversal of the expression tree. Each node is visited exactly once, and at each node, we performO(1)
operations (arithmetic operations or returning a value). Since the tree hasn
nodes (one for each element in the postfix expression), this also takesO(n)
time. - Overall time complexity:
O(n) + O(n) = O(n)
Space Complexity: O(n)
where n
is the length of the postfix expression array.
- The
buildTree
method uses a stack that can contain at most(n+1)/2
nodes in the worst case (when all operands appear before all operators). This occurs with expressions like"3 4 5 + *"
where operands stack up before being consumed by operators. - The expression tree itself contains exactly
n
nodes, requiringO(n)
space. - The
evaluate
method uses the call stack for recursion. In the worst case (a completely unbalanced tree), the recursion depth can beO(n)
. In a balanced expression tree, the recursion depth would beO(log n)
. - Overall space complexity:
O(n)
for the tree structure plusO(n)
for either the build stack or the recursion stack in the worst case, resulting inO(n)
total space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Order When Popping Children for Operators
One of the most frequent mistakes is reversing the order when assigning left and right children during tree construction. Since a stack follows LIFO (Last In, First Out) order, the operands are popped in reverse order of how they appear in the original expression.
Incorrect Implementation:
if not token.isdigit(): node.left = stack.pop() # Wrong! This gets the second operand node.right = stack.pop() # Wrong! This gets the first operand
Why This Fails:
For the expression 5 - 3
with postfix ["5", "3", "-"]
:
- Stack after processing "5" and "3": [5, 3]
- When processing "-", if we incorrectly assign:
node.left = stack.pop()
→ left = 3node.right = stack.pop()
→ right = 5
- This creates the tree representing
3 - 5 = -2
instead of5 - 3 = 2
Correct Implementation:
if not token.isdigit(): node.right = stack.pop() # Pop second operand first (becomes right child) node.left = stack.pop() # Pop first operand second (becomes left child)
2. Integer Division Handling
Another common mistake involves division operations, particularly with negative numbers.
Potential Issue:
elif self.value == '/': return left_result / right_result # Wrong! Returns float
Problems:
- Python's
/
operator returns a float, not an integer - The behavior of integer division with negative numbers can be unexpected
- Python's
//
operator floors toward negative infinity, not toward zero
Better Implementation for C++/Java-like Behavior:
elif self.value == '/':
# For behavior consistent with C++/Java (truncation toward zero)
return int(left_result / right_result)
# Or use // for Python's floor division (toward negative infinity)
# return left_result // right_result
3. Not Handling Negative Numbers in Input
The current implementation assumes all numeric tokens are positive single digits using isdigit()
. This fails for negative numbers.
Problem Scenario:
postfix = ["-5", "3", "+"] # Represents -5 + 3 # The token "-5" would be incorrectly treated as an operator
Robust Solution:
def is_operator(self, token: str) -> bool:
return token in {'+', '-', '*', '/'}
def buildTree(self, postfix: List[str]) -> Node:
stack = []
for token in postfix:
node = ExpressionNode(token)
if self.is_operator(token):
node.right = stack.pop()
node.left = stack.pop()
stack.append(node)
return stack[-1]
4. Empty Stack or Invalid Postfix Expression
The code doesn't validate that the postfix expression is well-formed.
Potential Failures:
# Not enough operands postfix = ["5", "+"] # Stack underflow when popping # Too many operands postfix = ["5", "3", "2"] # Multiple nodes left in stack # Empty input postfix = [] # IndexError when accessing stack[-1]
Defensive Implementation:
def buildTree(self, postfix: List[str]) -> Node:
if not postfix:
raise ValueError("Empty postfix expression")
stack = []
for token in postfix:
node = ExpressionNode(token)
if not token.isdigit():
if len(stack) < 2:
raise ValueError(f"Invalid postfix: insufficient operands for {token}")
node.right = stack.pop()
node.left = stack.pop()
stack.append(node)
if len(stack) != 1:
raise ValueError(f"Invalid postfix: {len(stack)} expressions remaining")
return stack[0]
5. Memory Management in Follow-up Extension
When extending to support more operators, avoid modifying the evaluate method directly. Instead, use a strategy pattern or operator mapping:
Extensible Design:
class ExpressionNode(Node):
# Define operator functions as a class variable
OPERATORS = {
'+': lambda a, b: a + b,
'-': lambda a, b: a - b,
'*': lambda a, b: a * b,
'/': lambda a, b: a // b,
# Easy to add more operators
'^': lambda a, b: a ** b,
'%': lambda a, b: a % b,
}
def evaluate(self) -> int:
if self.value.isdigit():
return int(self.value)
left_result = self.left.evaluate()
right_result = self.right.evaluate()
if self.value in self.OPERATORS:
return self.OPERATORS[self.value](left_result, right_result)
else:
raise ValueError(f"Unknown operator: {self.value}")
These pitfalls highlight the importance of careful attention to stack operations, proper handling of edge cases, and designing for extensibility from the start.
Which type of traversal does breadth first search do?
Recommended Readings
Stack Intro Imagine you have a pile of books on your desk If you want to add a new book you place it on top If you want to read a book you take it from the top And if you simply want to see which book is on the top you
Everything About Trees A tree is a type of graph data structure composed of nodes and edges Its main properties are It is acyclic doesn't contain any cycles There exists a path from the root to any node Has N 1 edges where N is the number of nodes in the tree and
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Want a Structured Path to Master System Design Too? Don’t Miss This!