Note Time O(n), Space O(n). Edge cases: empty string (valid), single character (invalid), only opening brackets (invalid). This is the quintessential stack problem — if you see matching/nesting, think stack.
Maintain a secondary stack that tracks the current minimum.
When pushing, also push to min stack if value <= current min.
When popping, also pop from min stack if value equals current min.
Note All operations O(1) time, O(n) extra space for the min stack. The trick: each entry in min_stack stores the minimum at that height of the main stack. Alternative: store (value, currentMin) tuples in one stack.
min stackminimum stackstack with getMinO(1) minimum
Evaluate Reverse Polish Notation
syntax
Process tokens left to right.
Numbers: push onto stack.
Operators: pop two operands, apply operator, push result.
example
// JavaScriptfunction evalRPN(tokens) {
const stack = [];
const ops = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => Math.trunc(a / b),
};
for (const token of tokens) {
if (token in ops) {
const b = stack.pop(), a = stack.pop();
stack.push(ops[token](a, b));
} else {
stack.push(Number(token));
}
}
return stack[0];
}
# Pythondef eval_rpn(tokens):
stack = []
ops = {'+', '-', '*', '/'}
for token in tokens:
if token in ops:
b, a = stack.pop(), stack.pop()
if token == '+': stack.append(a + b)
elif token == '-': stack.append(a - b)
elif token == '*': stack.append(a * b)
else: stack.append(int(a / b)) # truncate toward zeroelse:
stack.append(int(token))
return stack[0]
output
evalRPN(['2','1','+','3','*']) → 9
((2+1)*3 = 9)
Note Time O(n), Space O(n). Watch out: division truncates toward zero (not floor). Order matters: first popped is right operand, second popped is left. For infix to postfix conversion, use the Shunting Yard algorithm.
Note Time O(n), Space O(n). Each element is pushed and popped at most once. Used in: stock span, daily temperatures, histogram problems. For circular arrays, iterate through the array twice (use i % n).
next greater elementmonotonic stackdaily temperaturesstock span
BFS with Queue
syntax
Use a queue (FIFO) for breadth-first traversal.
Process level by level.
Enqueue neighbors/children, dequeue to process.
example
// JavaScript — BFS level order traversal of binary treefunction levelOrder(root) {
if (!root) return [];
const result = [];
const queue = [root];
while (queue.length > 0) {
const levelSize = queue.length;
const level = [];
for (let i = 0; i < levelSize; i++) {
const node = queue.shift();
level.push(node.val);
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
result.push(level);
}
return result;
}
# Pythonfrom collections import deque
def level_order(root):
ifnot root:
return []
result = []
queue = deque([root])
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level)
return result
output
Tree: 3
/ \
9 20
→ [[3], [9, 20]]
Note Time O(n), Space O(n). Use deque in Python for O(1) popleft — list.pop(0) is O(n). The 'capture level size' trick (for loop with current queue length) lets you process one level at a time. BFS is the go-to for shortest path in unweighted graphs.
BFS queuelevel order traversalbreadth first searchqueue
Monotonic Stack Pattern
syntax
A stack that maintains elements in sorted order (increasing or decreasing).
Before pushing, pop all elements that violate the ordering.
Used for: next greater/smaller, largest rectangle in histogram.
example
// JavaScript — Largest rectangle in histogramfunction largestRectangle(heights) {
const stack = []; // indices of increasing heightslet maxArea = 0;
for (let i = 0; i <= heights.length; i++) {
const h = i < heights.length ? heights[i] : 0;
while (stack.length > 0 && h < heights[stack[stack.length - 1]]) {
const height = heights[stack.pop()];
const width = stack.length === 0 ? i : i - stack[stack.length - 1] - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
}
# Pythondef largest_rectangle(heights):
stack = []
max_area = 0for i in range(len(heights) + 1):
h = heights[i] if i < len(heights) else0while stack and h < heights[stack[-1]]:
height = heights[stack.pop()]
width = i ifnot stack else i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
return max_area
Note Time O(n), Space O(n). The sentinel value (appending 0 at the end) forces all remaining bars to be processed. This is a hard problem but the monotonic stack template is reusable. Variant: maximal rectangle in a binary matrix applies this per row.