Stack
Expert Answer & Key Takeaways
Stack: The LIFO Mental Model
1. Core Operations & Complexity
| Operation | Description | Time Complexity | Space Complexity |
|---|---|---|---|
Push(x) | Add element x to the top. | total | |
Pop() | Remove and return the top element. | ||
Peek() / Top() | Return the top element without removing it. | ||
IsEmpty() | Check if the stack has no elements. |
2. When to Use a Stack?
Key Signals in Interviews:
- Parsing/Matching: Strings with brackets, tags (HTML/XML), or valid substructures.
- "Undo" or Backtracking: Reversing the most recent action (e.g., maze paths, DFS).
- Deferring Execution: Postponing evaluation until sufficient data is available (Evaluators, RPN).
- Next Greater/Smaller Elements: Finding the closest element that breaks a trend.
3. Stack vs. Recursion
- Implicit Stack: In recursion, the computer maintains a "Call Stack" for you. If the recursion is too deep, you get a
StackOverflowError. - Explicit Stack: Using an
ObjectorArrayin heaps, you can often handle deeper levels of nesting and have more control over the state.
4. The Power of the Monotonic Stack
How it works:
Goal: Find the Next Greater Element for [2, 1, 2, 4, 3]
Constraint: Stack must be Monotonic Decreasing (store unresolved elements)
1. Process '2': Stack [2]
2. Process '1': 1 < 2, so keep it. Stack [2, 1]
3. Process '2': 2 > 1. Violated!
- Pop '1'. The next greater for '1' is '2'.
- Push '2'. Stack [2, 2]
4. Process '4': 4 > 2. Violated!
- Pop '2'. Next greater is '4'.
- Pop '2'. Next greater is '4'.
- Push '4'. Stack [4]
5. Process '3': 3 < 4, so keep it. Stack [4, 3][!TIP] Monotonic Decreasing Stack: Use to find the Next Greater Element. Monotonic Increasing Stack: Use to find the Next Smaller Element (or previous smaller).
Valid Parentheses
s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
Visual Representation
s = "{ [ ] }"
Step 1: '{' -> Push to Stack. Stack: ['{']
Step 2: '[' -> Push to Stack. Stack: ['{', '[']
Step 3: ']' -> Matches Top '['. Pop. Stack: ['{']
Step 4: '}' -> Matches Top '{'. Pop. Stack: []
Result: Valid (Stack is Empty)Examples
Level I: Brute Force (String Replace)
Intuition
(), {}, [] until the string is empty or no more replacements can be made.Level II: Recursive (Function Call Stack)
Intuition
Level III: Optimal (Stack Mapping)
Intuition
Detailed Dry Run
| Char | Action | Stack Status | Match? |
|---|---|---|---|
| '(' | Push ')' | [')'] | - |
| '[' | Push ']' | [')', ']'] | - |
| ']' | Pop | [')'] | Yes |
| ')' | Pop | [] | Yes |
⚠️ Common Pitfalls & Tips
Min Stack
Visual Representation
Push: -2, 0, -3
Stack: MinStack:
| -3 | | -3 |
| 0 | | -2 |
| -2 | | -2 |
+----+ +----+
getMin() -> -3
pop()
top() -> 0
getMin() -> -2Examples
Level I: Single Stack (Brute Force Min)
Intuition
push, pop, and top. For getMin(), iterate over the entire stack to find the minimum value. This saves space over a two-stack approach but sacrifices the constant-time operation for querying the minimum.Level II: Single Stack (Value-Min Pairs)
Intuition
(current_value, current_min_so_far). This is conceptually simpler and ensures the value and its corresponding minimum are always synchronized.Level III: Optimal (Two Stacks)
Intuition
Detailed Dry Run
| Operation | Value | Stack | MinStack | Output |
|---|---|---|---|---|
| push | -2 | [-2] | [-2] | - |
| push | 0 | [-2, 0] | [-2] | - |
| push | -3 | [-2, 0, -3] | [-2, -3] | - |
| getMin | - | - | - | -3 |
| pop | - | [-2, 0] | [-2] | - |
⚠️ Common Pitfalls & Tips
.equals() instead of == for Stack comparisons as Integer objects might be outside the cache range.Implement Queue using Stacks
Examples
Level I: Two Stacks (Push O(N))
Intuition
Level II: Recursive (One Stack)
Intuition
Level III: Amortized O(1) with Two Stacks
input stack to handle pushes and an output stack for peeks/pops. When the output stack is empty, transfer all elements from input to output. This reverses the order to FIFO.Detailed Dry Run
| Operation | Value | in_stack | out_stack | Output |
|---|---|---|---|---|
| push | 1 | [1] | [] | - |
| push | 2 | [1, 2] | [] | - |
| peek | - | [] | [2, 1] | 1 |
| pop | - | [] | [2] | 1 |
| empty | - | [] | [2] | false |
Implement Stack using Queues
Examples
Level I: Two Queues (Push O(N))
Intuition
Level III: One Queue (Optimize Space)
Detailed Dry Run
| Operation | Value | Queue State | Action |
|---|---|---|---|
| push | 1 | [1] | Add 1 |
| push | 2 | [1, 2] -> [2, 1] | Add 2, rotate 1 element |
| pop | - | [1] | Pop front (2) |
| empty | - | [1] | Check if empty |
Evaluate Reverse Polish Notation
+, -, *, and /.Visual Representation
Tokens: ["2", "1", "+", "3", "*"]
1. Token "2": Push. Stack: [2]
2. Token "1": Push. Stack: [2, 1]
3. Token "+": Pop 1, Pop 2. Res = 2 + 1 = 3. Push. Stack: [3]
4. Token "3": Push. Stack: [3, 3]
5. Token "*": Pop 3, Pop 3. Res = 3 * 3 = 9. Push. Stack: [9]
Result: 9Examples
Level I: Brute Force (Recursive Evaluation)
Intuition
Level III: Optimal (Stack Evaluation)
Intuition
Detailed Dry Run
| Token | Action | Stack Status | Calculated |
|---|---|---|---|
| "2" | Push | [2] | - |
| "1" | Push | [2, 1] | - |
| "+" | Pop, Pop, Add | [3] | 2 + 1 = 3 |
| "3" | Push | [3, 3] | - |
| "*" | Pop, Pop, Mul | [9] | 3 * 3 = 9 |
⚠️ Common Pitfalls & Tips
int(a/b)) and JavaScript (Math.trunc(a/b)), as they must truncate toward zero.Daily Temperatures
temperatures, return an array answer such that answer[i] is the number of days you have to wait after the i-th day to get a warmer temperature. If there is no future day, keep answer[i] == 0.Visual Representation
temps = [73, 74, 75, 71, 69, 72, 76, 73]
Stack (indices of waiting days):
1. i=0 (73): Push 0. Stack: [0]
2. i=1 (74): 74 > 73. Pop 0, ans[0]=1-0=1. Push 1. Stack: [1]
3. i=2 (75): 75 > 74. Pop 1, ans[1]=2-1=1. Push 2. Stack: [2]
4. i=3 (71): Push 3. Stack: [2, 3]
5. i=4 (69): Push 4. Stack: [2, 3, 4]
6. i=5 (72): 72 > 69. Pop 4, ans[4]=1. 72 > 71. Pop 3, ans[3]=2. Stack: [2, 5]
7. i=6 (76): 76 > 72. Pop 5, ans[5]=1. 76 > 75. Pop 2, ans[2]=4. Stack: [6]Examples
Level I: Brute Force (Nested Loops)
Intuition
Level III: Optimal (Monotonic Stack)
Intuition
Detailed Dry Run
| i | Temp | Action | Stack Status | ans[idx] |
|---|---|---|---|---|
| 3 | 71 | Push | [2, 3] | - |
| 4 | 69 | Push | [2, 3, 4] | - |
| 5 | 72 | Pop 4, Pop 3 | [2, 5] | ans[4]=1, ans[3]=2 |
| 6 | 76 | Pop 5, Pop 2 | [6] | ans[5]=1, ans[2]=4 |
⚠️ Common Pitfalls & Tips
Next Greater Element I
nums1 within nums2. The next greater element of x in nums2 is the first element to its right that is larger than x.Visual Representation
nums1 = [4, 1, 2], nums2 = [1, 3, 4, 2]
Processing nums2 to find next greater:
1. 1: Stack [1]
2. 3: 3 > 1. Map[1]=3. Pop, Push 3. Stack [3]
3. 4: 4 > 3. Map[3]=4. Pop, Push 4. Stack [4]
4. 2: 2 < 4. Push 2. Stack [4, 2]
Result Map: {1:3, 3:4}
For nums1: 4 -> -1, 1 -> 3, 2 -> -1
Output: [-1, 3, -1]Examples
Level I: Brute Force (Nested Loops)
Intuition
nums1, find its position in nums2, then linearly scan rightward to find the first element greater than it. Simple, but performs redundant scans.Level II: Pre-located Search (Map + Scan)
Intuition
nums1 in nums2 every time, we can pre-store the indices of all elements in nums2 in a hash map. This allows us to jump directly to the correct starting point in nums2 for the scan, eliminating the 'find index' part of the brute force.Level III: Optimal (Monotonic Stack + HashMap)
Intuition
nums2 in a single pass. Store the results in a hash map for O(1) lookups when processing nums1.Detailed Dry Run
| Num (nums2) | Stack | Map Update | Action |
|---|---|---|---|
| 1 | [1] | - | Push |
| 3 | [3] | 1 -> 3 | Pop 1, Push 3 |
| 4 | [4] | 3 -> 4 | Pop 3, Push 4 |
| 2 | [4, 2] | - | Push |
⚠️ Common Pitfalls & Tips
nums1 is actually a subset of nums2 as per problem constraints. The stack approach only works for finding the next greater element.Next Greater Element II
nums, return the next greater number for every element. Circularly means after the last element, we search from the beginning.Visual Representation
nums = [1, 2, 1]
Pass 1:
1. Index 0 (1): Stack [0]
2. Index 1 (2): 2 > 1. ans[0]=2. Pop 0, Push 1. Stack [1]
3. Index 2 (1): 1 < 2. Push 2. Stack [1, 2]
Pass 2 (Circular):
4. i=0 (1): 1 < 1 (top). Skip.
5. i=1 (2): 2 > 1 (top). ans[2]=2. Pop 2. Stack [1]
Final Result: [2, -1, 2]Examples
Level I: Brute Force (Double Pass Circular Scan)
Intuition
Level II: Circular Brute Force (Modulo Operator)
Intuition
% to wrap around. For each element at index i, we check elements from (i+1) % n to (i + n - 1) % n. This is the same complexity as Level I but emphasizes the use of modular arithmetic for circular data structures.Level III: Optimal (Monotonic Stack, Double Pass)
Intuition
0 to 2N-1 and use modulo i % N to access elements. A monotonic stack stores indices of elements looking for their next greater neighbor.Detailed Dry Run
| i | i % N | Val | Stack | ans Update |
|---|---|---|---|---|
| 0 | 0 | 1 | [0] | - |
| 1 | 1 | 2 | [1] | ans[0]=2 |
| 2 | 2 | 1 | [1, 2] | - |
| 3 | 0 | 1 | [1, 2] | - |
| 4 | 1 | 2 | [1] | ans[2]=2 |
⚠️ Common Pitfalls & Tips
i % n is essential for circular behavior. Only push to the stack in the first pass i < n to avoid infinite loops or duplicates.Largest Rectangle in Histogram
heights representing the histogram's bar height where the width of each bar is 1, find the area of the largest rectangle in the histogram.Visual Representation
heights = [2, 1, 5, 6, 2, 3]
Processing:
1. 2: Stack [2]
2. 1: 1 < 2. Pop 2. Area = 2 * (1) = 2. Push 1.
3. 5: 5 > 1. Push 5.
4. 6: 6 > 5. Push 6.
5. 2: 2 < 6. Pop 6. Area = 6 * (1) = 6.
2 < 5. Pop 5. Area = 5 * (2) = 10.
Push 2.
...
Max Area: 10 (from heights 5 and 6)Examples
Level I: Brute Force (All Pairs)
Intuition
Level III: Optimal (Monotonic Stack)
Intuition
Detailed Dry Run
| i | h[i] | Stack | Action | Area Calculation |
|---|---|---|---|---|
| 0 | 2 | [0] | Push | - |
| 1 | 1 | [1] | Pop 0 | h[0]=2, w=1-0=1, Area=2 |
| 2 | 5 | [1, 2] | Push | - |
| 3 | 6 | [1, 2, 3] | Push | - |
| 4 | 2 | [1, 4] | Pop 3, 2 | h[3]=6, w=4-2-1=1, A=6; h[2]=5, w=4-1-1=2, A=10 |
Maximal Rectangle
rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.Visual Representation
Matrix:
[ ["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"] ]
Row 0: [1, 0, 1, 0, 0] -> Hist Max: 1
Row 1: [2, 0, 2, 1, 1] -> Hist Max: 2
Row 2: [3, 1, 3, 2, 2] -> Hist Max: 6 (The answer)
Row 3: [4, 0, 0, 3, 0] -> Hist Max: 4Examples
Level III: Optimal (Histogram per Row)
Intuition
Trapping Rain Water
n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.Visual Representation
heights = [0, 1, 0, 2]
1. Index 0 (0): Push 0.
2. Index 1 (1): 1 > 0. Pop 0. Stack empty. Push 1.
3. Index 2 (0): 0 < 1. Push 2.
4. Index 3 (2): 2 > 0. Pop 2 (bottom). Top is 1 (left wall).
- height = min(2, 1) - 0 = 1
- width = 3 - 1 - 1 = 1
- Water = 1 * 1 = 1Examples
Level III: Optimal (Monotonic Stack)
Intuition
Simplify Path
Visual Representation
path = "/home//foo/../bar/"
Tokens: ["home", "", "foo", "..", "bar"]
1. "home": Valid name. Push. Stack: ["home"]
2. "": Empty. Skip.
3. "foo": Valid name. Push. Stack: ["home", "foo"]
4. "..": Parent dir. Pop. Stack: ["home"]
5. "bar": Valid name. Push. Stack: ["home", "bar"]
Canonical Path: "/home/bar"Examples
Level I: Iterative Stack Processing (Natural Approach)
Intuition
Level II: Recursive Path Reduction
Intuition
/./ with / and /directory_name/../ with /. This is less efficient but helpful for understanding the underlying LIFO structure of the path.Level III: Optimal (Stack Tokenization)
Intuition
/ and process each component. A stack maintains the valid directory structure. .. removes the last added directory, while . or empty strings are ignored. Any other string is a valid directory to be pushed.Detailed Dry Run
| Part | Action | Stack Content |
|---|---|---|
| "home" | Push | ["home"] |
| "foo" | Push | ["home", "foo"] |
| ".." | Pop | ["home"] |
| "bar" | Push | ["home", "bar"] |
⚠️ Common Pitfalls & Tips
.. at the root keeps you at the root. The trailing slash should be removed unless it's the root itself.Generate Parentheses
The Catalan Connection
n pairs of parentheses is the n-th Catalan Number: . This grows roughly as .Validity Conditions
- Balance: At any point, the number of closing brackets
)does not exceed the number of opening brackets(. - Target: The total number of opening brackets does not exceed
n. - Finality: The total length is
2nand the final counts of(and)are equal.
Search Space Pruning
n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.Examples
Level I: Brute Force (Generate and Validate)
Intuition
2n consisting of '(' and ')'. Check each string for validity using a stack or a counter.Detailed Dry Run
Level II: Optimized Backtracking (Keeping Balance)
Intuition
n of them, and only add ')' if the number of ')' is less than the number of '('.open and close counts. If open < n, we can branch with '('. If close < open, we can branch with ')'.Detailed Dry Run
- "(" (open=1, close=0)
- "((" (open=2, close=0)
- "(()" (open=2, close=1)
- "(())" (open=2, close=2) -> SUCCESS
- "(()" (open=2, close=1)
- "()" (open=1, close=1)
- "()(" (open=2, close=1)
- "()()" (open=2, close=2) -> SUCCESS
- "()(" (open=2, close=1)
- "((" (open=2, close=0)
Level III: Closure Number (Divide and Conquer)
Intuition
S can be uniquely written as (A)B, where A and B are valid (potentially empty) parenthesis strings.2n, we iterate over all possible lengths of A. For a fixed i, where i is the number of pairs in A, we have n-i-1 pairs in B.Detailed Dry Run
- i=0: (empty) B where B is len 1. Results: "()()"
- i=1: (len 1) empty. Results: "(())"
Asteroid Collision
Visual Representation
asteroids = [5, 10, -5]
1. 5: Push. Stack: [5]
2. 10: Push (same direction). Stack: [5, 10]
3. -5: Moves left. 10 > |-5|. -5 explodes.
Final State: [5, 10]Examples
Level I: Brute Force (Repeated Simulation)
Intuition
Level III: Optimal (Stack Simulation)
Intuition
Detailed Dry Run
| Ast | Action | Stack Status | Collision Result |
|---|---|---|---|
| 5 | Push | [5] | - |
| 10 | Push | [5, 10] | - |
| -5 | Compare | [5, 10] | -5 explodes (10 > 5) |
| -12 | Compare | [] | 10 explodes, 5 explodes, -12 stays |
⚠️ Common Pitfalls & Tips
Remove All Adjacent Duplicates in String II
k adjacent and equal characters from string s until no more such removals are possible.Visual Representation
s = "deeedbbcccbdaa", k = 3
1. Process 'd': Stack [(d, 1)]
2. Process 'e': Stack [(d, 1), (e, 1)]
3. Process 'e': Stack [(d, 1), (e, 2)]
4. Process 'e': Stack [(d, 1), (e, 3)] -> Count=3! Pop (e).
5. Process 'd': Stack [(d, 2)]
...
Result: "aa"Examples
Level I: Brute Force (Repeated Removal)
Intuition
Level III: Optimal (Stack of Char-Count Pairs)
Intuition
k, pop it. If it doesn't match, push a new pair (char, 1).Detailed Dry Run
| Char | Action | Stack (Top Pair) | Length |
|---|---|---|---|
| 'd' | Push | (d, 1) | 1 |
| 'e' | Push | (e, 1) | 2 |
| 'e' | Incr | (e, 2) | 2 |
| 'e' | Pop | - | 1 |
⚠️ Common Pitfalls & Tips
Online Stock Span
Visual Representation
Prices: [100, 80, 60, 70, 60, 75, 85]
1. 100: Push (100, 1). Stack: [(100, 1)]
2. 80: Push (80, 1). Stack: [(100, 1), (80, 1)]
3. 70: Pop 60(1). Push (70, 2). Stack: [(100, 1), (80, 1), (70, 2)]
4. 75: Pop 60(1), 70(2). Push (75, 4). Stack: [(100, 1), (80, 1), (75, 4)]Examples
Level I: Brute Force (Linear Lookback per Query)
Intuition
Level III: Optimal (Monotonic Decreasing Stack)
Intuition
(price, span). When a new price is added, pop all elements with price less than or equal to the current one, adding their spans to the current span before pushing it onto the stack.Detailed Dry Run
| price | Action | Stack Status | Span Output |
|---|---|---|---|
| 100 | Push | [(100, 1)] | 1 |
| 80 | Push | [(100, 1), (80, 1)] | 1 |
| 70 | Pop 60(1) | [(100, 1), (80, 1), (70, 2)] | 2 |
| 85 | Pop 75, 80 | [(100, 1), (85, 6)] | 6 |
⚠️ Common Pitfalls & Tips
span += stack.pop()[1] so that the current element captures all smaller previous spans in constant time.Validate Stack Sequences
popped could have resulted from a sequence of pushed operations on an empty stack.Visual Representation
pushed = [1, 2, 3], popped = [2, 3, 1]
1. Push 1: Stack [1]
2. Push 2: Stack [1, 2]. Top 2 == popped[0]. Pop. Stack [1]
3. Push 3: Stack [1, 3]. Top 3 == popped[1]. Pop. Stack [1]
4. No more pushes. Top 1 == popped[2]. Pop. Stack []
Result: TrueExamples
Level I: Brute Force (Try All Push/Pop Orders)
Intuition
Level III: Optimal (Greedy Simulation)
Intuition
pushed array and push each element onto a stack. After each push, greedily pop elements from the stack as long as the stack top matches the current element in the popped array.Detailed Dry Run
| Push | Stack | Popped Pointer | Action |
|---|---|---|---|
| 1 | [1] | 0 | Push |
| 2 | [1, 2] | 0 | Push |
| - | [1] | 1 (2 matched) | Pop |
| 3 | [1, 3] | 1 | Push |
| - | [] | 3 (3 then 1 matched) | Pop, Pop |
⚠️ Common Pitfalls & Tips
pushed and popped are distinct as per standard constraints. Ensure you pop as many matching elements as possible after each push.Basic Calculator II
+, -, *, / operators and empty spaces.Visual Representation
s = "3+2*2"
1. '3': num = 3
2. '+': Push 3. num = 0, sign = '+'
3. '2': num = 2
4. '*': 2*2 = 4 (High precedence).
5. Result: 3 + 4 = 7Examples
Level I: Brute Force (Two-Pass: First Handle *, / Then +, -)
Intuition
* and / and evaluate them in-place (replacing the two operands and the operator with the result). Then, sum all remaining numbers separated by + and -. This avoids the stack but requires two traversals.Level III: Optimal (Single Stack Simulation)
Intuition
+ and -, push the number (negatively for -). For * and /, pop the last value, perform the operation with the current number, and push it back. Finally, sum the stack.Detailed Dry Run
| Char | Num | Sign | Stack | Action |
|---|---|---|---|---|
| '3' | 3 | '+' | [] | - |
| '+' | 0 | '+' | [3] | Push 3 |
| '2' | 2 | '+' | [3] | - |
| '*' | 0 | '*' | [3] | - |
| '2' | 2 | '*' | [3] | - |
| End | - | - | [3, 4] | Pop 2, Push 2*2 |
⚠️ Common Pitfalls & Tips
Decode String
k[encoded_string] means encoded_string is repeated k times.Visual Representation
s = "3[a]2[bc]"
1. '3': k = 3
2. '[': Push 3, Push "". Stack: [(3, "")]
3. 'a': curr = "a"
4. ']': Pop 3. res = "" + "a"*3 = "aaa"
5. '2': k = 2
6. '[': Push 2, Push "aaa". Stack: [(2, "aaa")]
7. "bc": curr = "bc"
8. ']': Pop 2. res = "aaa" + "bc"*2 = "aaabcbc"Examples
Level I: Brute Force (Innermost Bracket First)
Intuition
[] bracket pair using regex or string searching, expand it (repeat the inner string by the preceding number), replace it in the original string, and repeat until no brackets remain. This naturally handles nested brackets by working from inside out.Level III: Optimal (Two Stacks)
Intuition
countStack) and one to store the strings built so far (resStack). When an opening bracket [ is met, push the current count and current string. When a closing bracket ] is met, pop the multiplier and the previous string, then append the repeated current string to the previous one.Detailed Dry Run
| Char | countStack | resStack | currStr |
|---|---|---|---|
| '3' | [] | [] | "" (k=3) |
| '[' | [3] | [""] | "" |
| 'a' | [3] | [""] | "a" |
| ']' | [] | [] | "aaa" |
⚠️ Common Pitfalls & Tips
100[a]) must be handled. Nested brackets are naturally handled by the stack.Remove Duplicate Letters
s so that every letter appears once. The result must be the smallest in lexicographical order among all possible results.Visual Representation
s = "bcabc"
Counts: {b:2, c:2, a:1}
1. 'b': Push. Stack: [b]. Counts: {b:1, c:2, a:1}
2. 'c': Push. Stack: [b, c]. Counts: {b:1, c:1, a:1}
3. 'a':
- 'c' > 'a' and c's count > 0. Pop c.
- 'b' > 'a' and b's count > 0. Pop b.
- Push 'a'. Stack: [a]. Counts: {b:1, c:1, a:0}
4. 'b': Push. Stack: [a, b]. Counts: {b:0, c:1, a:0}
5. 'c': Push. Stack: [a, b, c]. Counts: {b:0, c:0, a:0}
Result: "abc"Examples
Level I: Generate All Subsequences, Filter, Then Sort
Intuition
Level III: Optimal (Greedy Monotonic Stack)
Intuition
seen set to skip characters already in the result.Detailed Dry Run
| Char | Action | Stack | Seen | Count Left |
|---|---|---|---|---|
| 'b' | Push | [b] | {b} | b:1 |
| 'c' | Push | [b, c] | {b, c} | c:1 |
| 'a' | Pop b, c; Push a | [a] | {a} | a:0 |
| 'b' | Push | [a, b] | {a, b} | b:0 |
⚠️ Common Pitfalls & Tips
Basic Calculator
(, ), +, -, non-negative integers and empty spaces.Visual Representation
s = " 1 + (4 + 5 - 2) - 3 "
1. '1': res = 1, sign = +
2. '+': Push current res (1) and sign (+) to stack.
3. '(': Start new group.
4. Groups: (4 + 5 - 2) = 7
5. Pop: 1 + (+)7 = 8
6. '-': res = 8, sign = -
7. '3': res = 8 - 3 = 5Examples
Level III: Optimal (Iterative with Stack)
Intuition
+ and -, apply them to the running total. For (, push the state; for ), pop and combine.Detailed Dry Run
| Char | Running Total | Sign | Stack |
|---|---|---|---|
| '1' | 1 | 1 | [] |
| '+' | 1 | 1 | [] |
| '(' | 0 | 1 | [(1, 1)] |
| '4' | 4 | 1 | [(1, 1)] |
⚠️ Common Pitfalls & Tips
Basic Calculator III
(, ), +, -, *, /, non-negative integers and spaces. This is the ultimate calculator problem.Visual Representation
s = "2*(5+5*2)/3+(6/2+8)"
1. Handle parentheses recursively or using a stack stack.
2. Within each group, apply multiply/divide first, then add/subtract.
3. Result: 2*(15)/3 + (11) = 10 + 11 = 21Examples
Level III: Optimal (Recursion with Deque/Index)
Intuition
(, we recurse; every time we see ), we return the result of the current sub-expression. Within each level, we use the standard 'accumulator' logic for +, -, *, /.⚠️ Common Pitfalls & Tips
+ at the end makes the loop logic cleaner for the last number. Be careful with division truncation in Python.Expression Add Operators
Precedence and Multiplication
+ and - is straightforward: just add or subtract the current value. However, multiplication (*) has higher precedence. If we have 1 + 2 * 3, we cannot simply compute (1 + 2) * 3.The Trick: Tracking Previous Operand
prev + current * next, we need to subtract current and add current * next.
Formula: NewTotal = (OldTotal - prevOperand) + (prevOperand * currentValue).Corner Cases
- Leading Zeros: A number like
"05"is invalid unless it's just"0". - Overflow: Since the target and intermediate values can exceed , use
long(64-bit integers).
num containing only digits and an integer target, return all possibilities to insert the binary operators +, -, and/or * between the digits of num so that the resultant expression evaluates to the target value.Examples
Level I: Basic Backtracking with Post-Evaluation
Intuition
Detailed Dry Run
- Try "1+2" -> eval(3) == 3 -> SUCCESS.
- Try "1-2" -> eval(-1) != 3.
- Try "1*2" -> eval(2) != 3.
Level II: Optimized Backtracking (Running Value)
Intuition
dfs(index, path, currentVal, prevOperand). If we add *, the new value is (currentVal - prevOperand) + (prevOperand * now).Detailed Dry Run
- Pick "1": val=1, prev=1.
- Pick "2" with "+": val=1+2=3, prev=2.
- Pick "3" with "+": val=3+3=6, prev=3. SUCCESS.
- Pick "2" with "": val=(1-1)+(12)=2, prev=2.
- Pick "3" with "": val=(2-2)+(23)=6, prev=6. SUCCESS.
Level III: Memory-Optimized Backtracking
Intuition
char[] or byte[] to build the path directly, avoiding string concatenations which are expensive.char[] (or byte[] in Go) to the recursive function. When adding an operator or digit, update the array and its current length. Backtrack by resetting the length.Detailed Dry Run
- path=['1'], len=1. dfs(1, 1, 1, path)
- path=['1','+','2'], len=3. dfs(2, 3, 2, path)
- path=['1','+','2','+','3'], len=5. dfs(3, 6, 3, path). Target hit. Add "1+2+3" to res.
- Backtrack: path=['1','+','2'], len=3. Try '*'.
- path=['1','+','2','','3'], len=5. dfs(3, 1+2-2+23=7, 2*3=6, path). Target not hit.
Course4All Technical Board
Verified ExpertSenior Software Engineers & Algorithmic Experts
Our DSA content is authored and reviewed by engineers from top tech firms to ensure optimal time and space complexity analysis.
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.