DSA & CodingInterview Prep

15 DSA Patterns That Solve Most Coding Interview Questions

The 15 data-structure and algorithm patterns behind most LeetCode and HackerRank interview problems — how to recognise each from the problem statement, a minimal Python template, typical complexity, and classic practice questions.

InterviewPilot TeamSeptember 19, 20267 min read

Grinding 500 random LeetCode problems is the slow way to get good at coding interviews. The fast way is noticing that most questions are the same 15 ideas wearing different costumes. Once you can say "this is a sliding window problem" in the first minute, the rest is execution.

For each pattern below: how to spot it, a minimal Python template, the usual complexity, and classic problems to practise. If you want the process for the interview itself, pair this with how to crack a DSA coding round.

1. Two pointers

Spot it: sorted array or string, pairs that sum to a target, removing duplicates in place, palindromes.

def pair_with_sum(nums, target):  # nums is sorted
    lo, hi = 0, len(nums) - 1
    while lo < hi:
        s = nums[lo] + nums[hi]
        if s == target:
            return lo, hi
        if s < target:
            lo += 1
        else:
            hi -= 1
    return None

Complexity: O(n) time, O(1) space. Practise: Two Sum II, 3Sum, Container With Most Water, Valid Palindrome.

2. Sliding window

Spot it: "longest / shortest / count of contiguous subarray or substring" with some condition.

def longest_unique_substring(s):
    seen, left, best = {}, 0, 0
    for right, ch in enumerate(s):
        if ch in seen and seen[ch] >= left:
            left = seen[ch] + 1
        seen[ch] = right
        best = max(best, right - left + 1)
    return best

Complexity: O(n). Practise: Longest Substring Without Repeating Characters, Minimum Window Substring, Max Consecutive Ones III.

3. Fast and slow pointers

Spot it: linked lists or sequences with possible cycles, finding the middle.

def has_cycle(head):
    slow = fast = head
    while fast and fast.next:
        slow, fast = slow.next, fast.next.next
        if slow is fast:
            return True
    return False

Complexity: O(n), O(1) space. Practise: Linked List Cycle II, Middle of the Linked List, Happy Number.

4. Binary search (including "on the answer")

Spot it: sorted input, or "find the minimum/maximum value such that a condition holds" where the condition is monotonic.

def min_capacity(weights, days):  # search the answer space
    def can_ship(cap):
        need, load = 1, 0
        for w in weights:
            if load + w > cap:
                need, load = need + 1, 0
            load += w
        return need <= days
 
    lo, hi = max(weights), sum(weights)
    while lo < hi:
        mid = (lo + hi) // 2
        if can_ship(mid):
            hi = mid
        else:
            lo = mid + 1
    return lo

Complexity: O(n log range). Practise: Search in Rotated Sorted Array, Koko Eating Bananas, Capacity to Ship Packages.

5. Prefix sums

Spot it: many range-sum queries, "number of subarrays summing to k".

def subarray_sum_count(nums, k):
    count, total, seen = 0, 0, {0: 1}
    for x in nums:
        total += x
        count += seen.get(total - k, 0)
        seen[total] = seen.get(total, 0) + 1
    return count

Complexity: O(n). Practise: Subarray Sum Equals K, Range Sum Query, Product of Array Except Self.

6. Hash map counting and grouping

Spot it: frequencies, anagrams, "first unique", de-duplication.

from collections import Counter, defaultdict
 
def group_anagrams(words):
    groups = defaultdict(list)
    for w in words:
        groups[tuple(sorted(w))].append(w)
    return list(groups.values())

Practise: Group Anagrams, Top K Frequent Elements, Longest Consecutive Sequence.

7. Monotonic stack

Spot it: "next greater / smaller element", spans, histogram areas.

def next_greater(nums):
    res, stack = [-1] * len(nums), []  # stack holds indices
    for i, x in enumerate(nums):
        while stack and nums[stack[-1]] < x:
            res[stack.pop()] = x
        stack.append(i)
    return res

Complexity: O(n). Practise: Daily Temperatures, Largest Rectangle in Histogram, Next Greater Element II.

8. Heap / top-K

Spot it: "k largest / smallest / most frequent", merging sorted streams, running median.

import heapq
 
def k_largest(nums, k):
    heap = []
    for x in nums:
        heapq.heappush(heap, x)
        if len(heap) > k:
            heapq.heappop(heap)
    return heap

Complexity: O(n log k). Practise: Kth Largest Element, Merge K Sorted Lists, Find Median from Data Stream.

9. Intervals

Spot it: meetings, bookings, overlapping ranges.

def merge(intervals):
    intervals.sort()
    out = [intervals[0]]
    for s, e in intervals[1:]:
        if s <= out[-1][1]:
            out[-1][1] = max(out[-1][1], e)
        else:
            out.append([s, e])
    return out

Complexity: O(n log n). Practise: Merge Intervals, Insert Interval, Meeting Rooms II.

Stuck on which pattern applies?

In a live coding round, InterviewPilot reads the problem off your screen and returns an Explained answer — the pattern, the approach, the code and its time and space complexity — so you can talk through the reasoning, not just paste a solution.

Try it free3 free sessions a day · Windows 10/11 · no card required

Spot it: shortest path in an unweighted graph or grid, "minimum number of steps", level-order traversal.

from collections import deque
 
def shortest_steps(grid, start, goal):
    rows, cols = len(grid), len(grid[0])
    q, seen = deque([(start, 0)]), {start}
    while q:
        (r, c), d = q.popleft()
        if (r, c) == goal:
            return d
        for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            nr, nc = r + dr, c + dc
            if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 0 and (nr, nc) not in seen:
                seen.add((nr, nc))
                q.append(((nr, nc), d + 1))
    return -1

Complexity: O(V + E). Practise: Rotting Oranges, Word Ladder, Binary Tree Level Order Traversal.

11. Depth-first search and backtracking

Spot it: "all combinations / permutations / subsets", islands, path existence.

def subsets(nums):
    res, path = [], []
    def dfs(i):
        if i == len(nums):
            res.append(path[:])
            return
        path.append(nums[i]); dfs(i + 1); path.pop()   # take it
        dfs(i + 1)                                       # skip it
    dfs(0)
    return res

Complexity: often exponential by nature (2ⁿ subsets). Practise: Number of Islands, Combination Sum, N-Queens, Word Search.

12. Topological sort

Spot it: tasks with prerequisites, build order, "is there a cycle in dependencies?"

from collections import deque, defaultdict
 
def course_order(n, prereqs):
    graph, indeg = defaultdict(list), [0] * n
    for course, pre in prereqs:
        graph[pre].append(course)
        indeg[course] += 1
    q = deque(i for i in range(n) if indeg[i] == 0)
    order = []
    while q:
        node = q.popleft()
        order.append(node)
        for nxt in graph[node]:
            indeg[nxt] -= 1
            if indeg[nxt] == 0:
                q.append(nxt)
    return order if len(order) == n else []  # [] means a cycle

Practise: Course Schedule I & II, Alien Dictionary.

13. Union-Find (disjoint set)

Spot it: connected components, "are these two in the same group?", redundant connections.

parent = list(range(n))
 
def find(x):
    while parent[x] != x:
        parent[x] = parent[parent[x]]  # path compression
        x = parent[x]
    return x
 
def union(a, b):
    ra, rb = find(a), find(b)
    if ra == rb:
        return False
    parent[ra] = rb
    return True

Practise: Number of Provinces, Redundant Connection, Accounts Merge.

14. Dynamic programming

Spot it: "number of ways", "minimum cost", "maximum value", choices at each step that overlap. Define the state, the transition and the base case — say them out loud before coding.

def coin_change(coins, amount):
    dp = [0] + [float('inf')] * amount
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a:
                dp[a] = min(dp[a], dp[a - c] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

Practise: Climbing Stairs, House Robber, Longest Common Subsequence, Coin Change, Edit Distance.

15. Trie

Spot it: prefix searches, autocomplete, word dictionaries.

class Trie:
    def __init__(self):
        self.root = {}
 
    def insert(self, word):
        node = self.root
        for ch in word:
            node = node.setdefault(ch, {})
        node['$'] = True
 
    def starts_with(self, prefix):
        node = self.root
        for ch in prefix:
            if ch not in node:
                return False
            node = node[ch]
        return True

Practise: Implement Trie, Word Search II, Design Add and Search Words.

Cheat sheet: trigger → pattern

If the problem says…Try…
Sorted array, pair/tripletTwo pointers, binary search
Contiguous subarray/substringSliding window, prefix sums
Minimum value that satisfies XBinary search on the answer
Top / smallest / most frequent kHeap
Next greater/smallerMonotonic stack
Overlapping rangesIntervals (sort first)
Minimum steps, unweightedBFS
All combinations/permutationsBacktracking
Prerequisites / orderingTopological sort
Connected groupsUnion-Find or DFS
Count ways / min cost with overlapDynamic programming
Prefix lookupTrie

Also read the constraints: n ≤ 20 suggests exponential backtracking is fine; n ≤ 10⁵ means you need O(n log n) or better.

How to practise so it sticks

  1. Pick one pattern per session; solve 5–8 problems of it back to back.
  2. Before coding each one, say the pattern and complexity out loud.
  3. Re-solve your mistakes three days later without looking.
  4. Mix patterns in the final two weeks so you practise recognition, not just execution.

Frequently asked questions

Was this article useful?

Discussion

No comments yet. Been through an interview like this? Your experience could help the next candidate.

You’re posting anonymously — it appears after a quick review. Sign in to post under your name instantly.
0/2000

Bring backup into your next round.

Install InterviewPilot, upload your resume, and walk in with structured answers a keystroke away — visible to you and nobody else.