Core Patterns โ Recognizing Structure Before Code
Strong engineers do not memorize solutions. They recognize structural moves.
A pattern is not a trick. It is a repeated structural strategy that appears across many problems.
Most patterns exist to eliminate repetition, preserve constraints, or change growth behavior.
Two Pointers
Two coordinated indices moving through data. Replace nested loops with synchronized movement.
function isPalindrome(str: string): boolean {
let left = 0
let right = str.length - 1
while (left < right) {
if (str[left] !== str[right]) return false
left++
right--
}
return true
}Time: O(n)
Space: O(1)
Mental Shift
Coordinate movement instead of comparing everything.
Sliding Window
Maintain a window that always satisfies a constraint. Avoid recomputing overlapping work.
function maxSubarraySum(arr: number[], k: number): number {
let sum = 0
for (let i = 0; i < k; i++) {
sum += arr[i]
}
let max = sum
for (let i = k; i < arr.length; i++) {
sum += arr[i] - arr[i - k]
max = Math.max(max, sum)
}
return max
}Time: O(n)
Space: O(1)
Mental Shift
Update incrementally while preserving a condition.
Prefix Sum
Precompute cumulative results to answer many range queries efficiently.
function buildPrefix(arr: number[]): number[] {
const prefix = [0]
for (let i = 0; i < arr.length; i++) {
prefix.push(prefix[i] + arr[i])
}
return prefix
}Build: O(n)
Query: O(1)
Mental Shift
Pay once. Query cheaply many times.
Binary Search
Repeatedly divide the search space. Only works when structure exists.
function binarySearch(arr: number[], target: number): number {
let left = 0
let right = arr.length - 1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (arr[mid] === target) return mid
if (arr[mid] < target) left = mid + 1
else right = mid - 1
}
return -1
}Time: O(log n)
BFS (Breadth-First Search)
Explore level by level. Guarantees shortest path in unweighted graphs.
function bfs(root: Node) {
const queue = [root]
while (queue.length) {
const node = queue.shift()!
console.log(node.value)
for (const child of node.children) {
queue.push(child)
}
}
}Time: O(V + E)
DFS (Depth-First Search)
Explore deeply before backtracking. Often pairs naturally with recursion.
function dfs(node: Node) {
if (!node) return
console.log(node.value)
for (const child of node.children) {
dfs(child)
}
}Time: O(V + E)
๐ง The Hidden Engine โ Invariants
Every strong pattern preserves something. That preserved truth is the invariant.
- Sliding Window โ the window always satisfies a constraint.
- Binary Search โ the target remains inside [left, right].
- BFS โ all processed nodes are at smaller distance.
- DFS โ visited prevents infinite loops.
If you cannot state the invariant clearly, you do not fully understand the pattern.
Invariants make algorithms predictable.
๐ง What All Patterns Share
- They eliminate repetition.
- They preserve invariants.
- They exploit structural constraints.
- They change growth behavior.
Final Insight
Patterns are not tricks.
They are structural moves guided by invariants.