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
// JavaScriptfunctionevalRPN(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];}
# Python
def 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 zero
else:
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.
Traversefrom right to left(or left to right).Maintain a decreasing stack.For each element, pop smaller elements - the top is the next greater.
Example
// JavaScriptfunctionnextGreaterElements(arr){const result =newArray(arr.length).fill(-1);const stack =[];// stores indicesfor(let i =0; i < arr.length; i++){while(stack.length>0&& arr[stack[stack.length-1]]< arr[i]){
result[stack.pop()]= arr[i];}
stack.push(i);}return result;}
# Python
def next_greater_elements(arr):
result =[-1]*len(arr)
stack =[] # stores indices
for i inrange(len(arr)):while stack and arr[stack[-1]]< arr[i]:
result[stack.pop()]= arr[i]
stack.append(i)return result
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 treefunctionlevelOrder(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):if not root:return[]
result =[]
queue =deque([root])while queue:
level =[]for _ inrange(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.Usedfor: next greater/smaller, largest rectangle in histogram.
Example
// JavaScript - Largest rectangle in histogramfunctionlargestRectangle(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;}
# Python
def largest_rectangle(heights):
stack =[]
max_area =0for i inrange(len(heights)+1):
h = heights[i]if i <len(heights)else0while stack and h < heights[stack[-1]]:
height = heights[stack.pop()]
width = i if not 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.