5 Patterns That Crack 90% of DSA Interview Questions
Most DSA problems are variations of just 5 core patterns. Learn them once, and you can solve hundreds of problems β even ones you've never seen before.
Every year, hundreds of thousands of Indian engineering students study DSA for placements. Most of them memorise solutions. A few understand patterns. Only the second group does well in interviews they haven't prepared for.
This article teaches you the 5 patterns. After reading, you won't just know how to solve Two Sum β you'll know why the approach works and how to apply the same thinking to 50 other problems.
Pattern 1: Two Pointers
What it solves: Problems on sorted arrays or strings where you need to find a pair, triplet, or window that satisfies a condition.
The core idea: Start one pointer at the left end and one at the right end. Move them toward each other based on the current sum/condition. This turns O(nΒ²) brute force into O(n).
When to recognise it: The problem involves a sorted array and asks you to find elements that sum to a target, or asks about palindromes, or involves removing duplicates in-place.
Example: Two Sum II (sorted input)
def two_sum(numbers, target):
left, right = 0, len(numbers) - 1
while left < right:
current_sum = numbers[left] + numbers[right]
if current_sum == target:
return [left + 1, right + 1] # 1-indexed
elif current_sum < target:
left += 1 # need bigger sum β move left pointer right
else:
right -= 1 # need smaller sum β move right pointer left
return []
Why it works: Because the array is sorted, if the sum is too small, the only way to increase it is to move the left pointer right. If it's too big, move the right pointer left. You never need to check pairs twice.
Problems to practice
- Valid Palindrome
- Container With Most Water
- 3Sum (sort first, then two pointers for each element)
- Trapping Rain Water
Pattern 2: Sliding Window
What it solves: Subarray or substring problems where you need to find the longest, shortest, or optimal contiguous sequence satisfying a condition.
The core idea: Maintain a window with two pointers (left and right). Expand right to grow the window. Shrink from the left when the window violates the condition. This avoids recomputing the sum/state of overlapping windows.
When to recognise it: Keywords like "subarray," "substring," "contiguous," "maximum length," "minimum length."
Example: Longest Substring Without Repeating Characters
def length_of_longest_substring(s):
char_set = set()
left = 0
max_len = 0
for right in range(len(s)):
# Shrink window until no duplicate
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
The template to remember:
- Add
s[right]to your window state - While window is invalid: remove
s[left], moveleftright - Update your answer using the current window
Problems to practice
- Maximum Sum Subarray of Size K (fixed window)
- Permutation in String
- Minimum Window Substring (hard)
- Max Consecutive Ones III
Pattern 3: Fast & Slow Pointers (Floyd's Algorithm)
What it solves: Cycle detection in linked lists or sequences. Also useful for finding the middle of a linked list.
The core idea: Move one pointer one step at a time ("slow") and another two steps at a time ("fast"). If there's a cycle, they'll eventually meet inside it. If there's no cycle, the fast pointer reaches the end.
When to recognise it: Linked list cycle problems, finding the middle of a linked list, duplicate detection in arrays with values in range [1, n].
Example: Detect Cycle in Linked List
def has_cycle(head):
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True # cycle detected
return False
Why they always meet: If a cycle exists, the fast pointer gains one step per iteration on the slow pointer (it moves 2, slow moves 1 = net gain of 1). Eventually the gap closes to 0 β they meet.
Finding the middle of a linked list
def find_middle(head):
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow # when fast reaches end, slow is at middle
Problems to practice
- Happy Number (apply fast/slow to the digit-sum sequence)
- Find the Duplicate Number
- Linked List Cycle II (find the start of the cycle)
- Reorder List (split at middle first)
Pattern 4: Hash Map for O(1) Lookup
What it solves: Any problem where brute force involves nested loops searching for a complement, frequency, or previously seen value.
The core idea: As you iterate, store everything you've seen in a hash map. For each new element, check the map in O(1) instead of scanning the array again in O(n). This collapses O(nΒ²) brute force to O(n).
When to recognise it: "Find two elements that sum to target," "find the first duplicate," "group elements by property," "count frequencies."
Example: Two Sum (unsorted)
def two_sum(nums, target):
seen = {} # value β index
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
The insight: For each number, the question becomes "have I seen target - num before?" The map answers that in O(1).
Subarray Sum Equals K β a harder application
def subarray_sum(nums, k):
count = 0
prefix_sum = 0
freq = {0: 1} # prefix_sum β how many times seen
for num in nums:
prefix_sum += num
# If (prefix_sum - k) was seen before, those subarrays sum to k
count += freq.get(prefix_sum - k, 0)
freq[prefix_sum] = freq.get(prefix_sum, 0) + 1
return count
Problems to practice
- Group Anagrams
- Top K Frequent Elements
- Longest Consecutive Sequence
- Valid Anagram
Pattern 5: BFS / DFS on Graphs and Trees
What it solves: Everything involving graphs (grids count!), trees, connected components, shortest paths, or cycle detection.
BFS (Breadth-First Search): Use when you need the shortest path or want to process nodes level by level.
DFS (Depth-First Search): Use when you need to explore all paths, detect cycles, do topological sort, or don't care about shortest distance.
BFS Template
from collections import deque
def bfs(graph, start):
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
DFS Template (recursive)
def dfs(graph, node, visited):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
Grid problems β treat the grid as a graph
def num_islands(grid):
if not grid:
return 0
count = 0
rows, cols = len(grid), len(grid[0])
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] != '1':
return
grid[r][c] = '0' # mark visited by changing to '0'
dfs(r+1, c)
dfs(r-1, c)
dfs(r, c+1)
dfs(r, c-1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1':
dfs(r, c)
count += 1
return count
Problems to practice
- Clone Graph
- Course Schedule (BFS topological sort)
- Pacific Atlantic Water Flow
- Word Ladder (BFS)
- Number of Islands, Rotting Oranges
How to Use These Patterns in an Interview
When you see a new problem, ask these questions in order:
- Is the input sorted or can I sort it? β Two Pointers might work
- Am I looking for a contiguous subarray or substring? β Sliding Window
- Is it a linked list with possible cycles? β Fast & Slow
- Am I doing repeated lookups inside a loop? β Hash Map
- Is it a tree, grid, or graph problem? β BFS or DFS (BFS for shortest path, DFS for everything else)
Most Medium problems fit cleanly into one pattern. Hard problems combine two or more β for example, Sliding Window + Hash Map, or DFS + Dynamic Programming.
The Fastest Way to Get Good
Don't try to do 200 problems. Do 40 problems very deliberately:
- 8 per pattern
- After each problem, write down which pattern you used and why
- When you're wrong about the pattern, understand why before moving on
That deliberate practice will do more than 200 mindless LeetCode attempts.
Next step: Open the Practice section and filter by each pattern. Start with Easy, then Medium. Use the AI Tutor when you're genuinely stuck β not before you've tried for 20 minutes.
Ready to practice what you just learned?
Apply these concepts with AI-powered tools built for CS students.