7 DSA Coding Patterns That Crack 80% of FAANG Interviews (2026)
Stop memorising individual problems. Learn the 7 core patterns — and you'll be able to solve hundreds of LeetCode problems you've never seen before.
📋 The 7 Patterns
Most interview candidates grind 200+ LeetCode problems randomly. The candidates who get offers study patterns. When you see a new problem in an interview, you don't need to have solved it before — you just need to recognize which pattern applies. Here are the 7 that matter most.
Use a window that expands right and shrinks from the left to process subarrays or substrings without re-scanning. Turns O(n²) brute force into O(n).
- Max/min subarray of size k
- Longest substring with condition
- Smallest subarray with sum ≥ target
- Non-contiguous elements
- 2D arrays
- Problems requiring backtracking
Classic Example: Longest substring without repeating characters
def lengthOfLongestSubstring(s):
char_set = set()
left = max_len = 0
for right in range(len(s)):
while s[right] in char_set:
char_set.remove(s[left])
left += 1
char_set.add(s[right])
max_len = max(max_len, right - left + 1)
return max_len
Use two indices (usually one from each end, or both starting left) that move toward each other or in the same direction. Works brilliantly on sorted arrays.
- Pair with target sum
- Palindrome check
- Remove duplicates in-place
- Unsorted arrays (usually)
- When order must be preserved
Classic Example: Two Sum II (sorted array)
def twoSum(numbers, target):
left, right = 0, len(numbers) - 1
while left < right:
s = numbers[left] + numbers[right]
if s == target: return [left+1, right+1]
elif s < target: left += 1
else: right -= 1
Also called Floyd's Cycle Detection. One pointer moves 1 step, another moves 2 steps. If there's a cycle, they'll eventually meet. Also finds the middle of a list.
Classic Example: Detect cycle in linked list
def hasCycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
# Find middle of linked list:
def middleNode(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow # slow is at the middle
BFS explores level by level using a queue. DFS goes deep first using recursion (or a stack). Together they solve nearly all tree and graph problems.
- Shortest path (unweighted)
- Level-order traversal
- Nearest neighbors
- Path existence problems
- Connected components
- Backtracking (permutations)
# BFS — Level order traversal
from collections import deque
def levelOrder(root):
if not 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
Break a problem into overlapping subproblems and store results to avoid recomputation. Two styles: Top-down (memoization) and Bottom-up (tabulation).
Classic Example: Fibonacci with memoization vs tabulation
# Memoization (Top-Down)
def fib_memo(n, memo={}):
if n <= 1: return n
if n not in memo:
memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
return memo[n]
# Tabulation (Bottom-Up) — O(1) space optimized
def fib_tab(n):
if n <= 1: return n
a, b = 0, 1
for _ in range(2, n+1):
a, b = b, a + b
return b
Don't just use Binary Search on sorted arrays. The advanced pattern is Binary Search on the answer space — when the answer has a monotonic property (feasibility increases/decreases with the value).
Classic Example: Find minimum capacity to ship packages within D days
def shipWithinDays(weights, days):
left, right = max(weights), sum(weights)
def canShip(capacity):
days_needed, current = 1, 0
for w in weights:
if current + w > capacity:
days_needed += 1
current = 0
current += w
return days_needed <= days
while left < right:
mid = (left + right) // 2
if canShip(mid): right = mid
else: left = mid + 1
return left
A heap gives you O(log n) insert and O(1) min/max access. Use a Min-Heap to track the K largest elements (counterintuitive but correct). Use a Max-Heap to track the K smallest.
Classic Example: K Most Frequent Elements
import heapq
from collections import Counter
def topKFrequent(nums, k):
freq = Counter(nums)
# Min-heap of size k: (frequency, element)
heap = []
for num, count in freq.items():
heapq.heappush(heap, (count, num))
if len(heap) > k:
heapq.heappop(heap) # remove smallest frequency
return [item[1] for item in heap]
Quick Pattern Recognition Guide
| Keywords in Problem | Pattern to Try |
|---|---|
| "subarray", "substring", "contiguous", "window" | Sliding Window |
| "sorted array", "pair", "triplet", "palindrome" | Two Pointers |
| "linked list", "cycle", "middle" | Fast & Slow Pointers |
| "shortest path", "level order", "connected" | BFS / DFS |
| "max/min subproblem", "count ways", "can you reach" | Dynamic Programming |
| "minimize maximum", "smallest X that..." | Binary Search on Answer |
| "top K", "K largest", "K closest", "median" | Heap / Priority Queue |
🚀 Put These Patterns to the Test
Take our 100-question DSA interactive quiz — free, no signup. Test every pattern with real interview-style questions and instant explanations.
Take the DSA Quiz → Get 300Q PDF Bundle
No comments:
Post a Comment