Master 10 Essential Algorithm Patterns for Coding Interviews
← Back to Blog
Algorithms15 min read

Master 10 Essential Algorithm Patterns for Coding Interviews

👤
Interview Whisper Team
November 1, 2025

Most candidates approach coding interviews the wrong way.

They memorize hundreds of individual problems. Grinding through LeetCode, trying to cover every possible question they might face.

But here's the secret top performers know: Most coding problems follow recognizable patterns.

Master these 10 patterns, and you'll be able to solve 80% of interview questions—even ones you've never seen before.

Instead of memorizing 500 problems, you'll understand the core concepts that unlock thousands of variations.

It's the difference between memorizing answers and understanding how to think.

Algorithm patterns and data structures for coding interviews

Why Patterns Matter

Think of algorithm patterns like chess openings.

You don't memorize every possible chess game—you learn strategic patterns that apply to thousands of games.

The same principle applies to coding interviews.

When you see a new problem, pattern recognition helps you immediately identify the approach. "This looks like a sliding window problem," you think, and suddenly you know exactly where to start.

No more blank stares. No more panic.

Benefits of pattern-based learning:

Solve new problems faster

Instead of staring blankly at an unfamiliar problem, you'll recognize the underlying pattern and apply the template you've practiced. First 30 seconds: problem identified.

Recognize variations of known problems

Most "new" interview questions are just variations of classic problems.

Patterns help you see through the disguise. They can reword it however they want—you'll still spot the pattern.

Build true problem-solving intuition

With patterns, you develop a sixth sense for which approach will work best—even before you start coding.

It's like the Matrix. Once you see the patterns, you can't unsee them.

Reduce interview stress

There's nothing more calming than thinking, "I've solved problems like this before!"

Pattern knowledge gives you confidence. And confidence shows.

Two pointers technique for array and string problems

Pattern #1: Two Pointers

The two pointers pattern is one of the most elegant techniques in your algorithmic toolkit. It uses two reference points that move through the data structure to find relationships or satisfy conditions.

When to use: Problems involving arrays, strings, or linked lists where you need to find pairs, triplets, or subarrays.

Key indicators:

When you see these phrases in a problem, think "two pointers":

"Find pair that sums to X" - Classic two pointers from both ends of a sorted array.

"Remove duplicates in sorted array" - One pointer reads, another writes unique values.

"Reverse a string" - Pointers start at opposite ends and swap inward.

"Container with most water" - Pointers maximize area by moving strategically.

Basic structure:

def two_pointers_template(arr):
    left = 0
    right = len(arr) - 1

    while left < right:
        # Calculate something with arr[left] and arr[right]
        if condition_met:
            return result
        elif left_should_move:
            left += 1
        else:
            right -= 1

    return result

Example problem: Two Sum (sorted array)

def two_sum_sorted(numbers, target):
    """
    Find two numbers that add up to target in sorted array.
    Time: O(n), Space: O(1)
    """
    left, right = 0, len(numbers) - 1

    while left < right:
        current_sum = numbers[left] + numbers[right]

        if current_sum == target:
            return [left, right]
        elif current_sum < target:
            left += 1  # Need bigger sum
        else:
            right -= 1  # Need smaller sum

    return []

# Test
print(two_sum_sorted([1, 2, 3, 4, 6], 6))  # [1, 3] → 2+4=6

More problems to practice:

  • 3Sum
  • Remove Nth Node From End
  • Trapping Rain Water
  • Valid Palindrome

Sliding window algorithm technique for substring problems

Pattern #2: Sliding Window

The sliding window pattern is perfect for problems involving contiguous sequences. Imagine a window sliding across your array or string, expanding and contracting as needed to find the optimal solution.

When to use: Problems involving subarrays or substrings with specific conditions.

Key indicators:

These problem descriptions scream "sliding window":

"Longest/shortest substring with..." - Window expands to find longest, contracts to find shortest.

"Maximum sum subarray of size K" - Fixed-size window slides to find maximum sum.

"Find all anagrams" - Window tracks character frequency to match patterns.

"Minimum window substring" - Dynamic window finds smallest substring containing all required characters.

Two types:

  1. Fixed size: Window size is constant
  2. Dynamic size: Window grows and shrinks

Fixed window template:

def fixed_sliding_window(arr, k):
    window_sum = sum(arr[:k])
    max_sum = window_sum

    for i in range(k, len(arr)):
        # Slide the window
        window_sum = window_sum - arr[i - k] + arr[i]
        max_sum = max(max_sum, window_sum)

    return max_sum

Dynamic window template:

def dynamic_sliding_window(s, condition):
    left = 0
    result = float('inf')
    current_state = {}

    for right in range(len(s)):
        # Expand window by including s[right]
        # Update current_state

        while condition_met:
            # Update result if needed
            # Shrink window from left
            left += 1

    return result

Example problem: Longest Substring Without Repeating Characters

def length_of_longest_substring(s):
    """
    Find length of longest substring without repeating characters.
    Time: O(n), Space: O(min(n, m)) where m is charset size
    """
    char_set = set()
    left = 0
    max_length = 0

    for right in range(len(s)):
        # Shrink window until no duplicates
        while s[right] in char_set:
            char_set.remove(s[left])
            left += 1

        # Add current character
        char_set.add(s[right])
        max_length = max(max_length, right - left + 1)

    return max_length

# Test
print(length_of_longest_substring("abcabcbb"))  # 3 (abc)
print(length_of_longest_substring("bbbbb"))     # 1 (b)

More problems to practice:

  • Maximum Sum Subarray of Size K
  • Fruits Into Baskets
  • Permutation in String
  • Minimum Window Substring

Pattern #3: Fast & Slow Pointers

When to use: Problems involving cycles or finding middle elements in linked lists.

Key indicators:

  • "Detect cycle"
  • "Find middle element"
  • "Happy number"
  • "Start of cycle"

Template:

def fast_slow_pointers(head):
    slow = head
    fast = head

    while fast and fast.next:
        slow = slow.next        # Move 1 step
        fast = fast.next.next   # Move 2 steps

        if slow == fast:
            return True  # Cycle detected

    return False  # No cycle

Example problem: Linked List Cycle

class ListNode:
    def __init__(self, val=0):
        self.val = val
        self.next = None

def has_cycle(head):
    """
    Detect if linked list has a cycle.
    Time: O(n), Space: O(1)
    """
    if not head or not head.next:
        return False

    slow = head
    fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow == fast:
            return True

    return False

Example problem: Middle of Linked List

def find_middle(head):
    """
    Find middle node of linked list.
    When fast reaches end, slow is at middle.
    Time: O(n), Space: O(1)
    """
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

    return slow

More problems to practice:

  • Happy Number
  • Start of LinkedList Cycle
  • Palindrome LinkedList

Pattern #4: Merge Intervals

When to use: Problems with overlapping intervals or ranges.

Key indicators:

  • "Merge overlapping intervals"
  • "Insert interval"
  • "Meeting rooms"
  • "Conflicting appointments"

Template:

def merge_intervals(intervals):
    if not intervals:
        return []

    # Sort by start time
    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        last = merged[-1]

        if current[0] <= last[1]:  # Overlapping
            # Merge by updating end time
            last[1] = max(last[1], current[1])
        else:
            merged.append(current)

    return merged

Example problem: Merge Intervals

def merge(intervals):
    """
    Merge all overlapping intervals.
    Time: O(n log n), Space: O(n)
    """
    if not intervals:
        return []

    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        if current[0] <= merged[-1][1]:
            # Overlapping - merge
            merged[-1][1] = max(merged[-1][1], current[1])
        else:
            # Non-overlapping - add new interval
            merged.append(current)

    return merged

# Test
print(merge([[1,3],[2,6],[8,10],[15,18]]))
# [[1,6],[8,10],[15,18]]

More problems to practice:

  • Insert Interval
  • Intervals Intersection
  • Meeting Rooms II
  • Employee Free Time

Pattern #5: Cyclic Sort

When to use: Problems with arrays containing numbers in a given range.

Key indicators:

  • "Find missing number in range [1, n]"
  • "Find duplicate number"
  • "Find all duplicates"
  • Numbers are in range [0, n] or [1, n]

Template:

def cyclic_sort(nums):
    i = 0
    while i < len(nums):
        correct_index = nums[i] - 1  # For range [1, n]
        # OR: correct_index = nums[i]  # For range [0, n-1]

        if nums[i] != nums[correct_index]:
            # Swap to correct position
            nums[i], nums[correct_index] = nums[correct_index], nums[i]
        else:
            i += 1

    return nums

Example problem: Find Missing Number

def find_missing_number(nums):
    """
    Find missing number in array [0, 1, ..., n].
    Time: O(n), Space: O(1)
    """
    i, n = 0, len(nums)

    # Place each number at its correct index
    while i < n:
        correct_index = nums[i]
        if nums[i] < n and nums[i] != nums[correct_index]:
            nums[i], nums[correct_index] = nums[correct_index], nums[i]
        else:
            i += 1

    # Find first missing number
    for i in range(n):
        if nums[i] != i:
            return i

    return n

# Test
print(find_missing_number([4, 0, 3, 1]))  # 2
print(find_missing_number([8, 3, 5, 2, 4, 6, 0, 1]))  # 7

More problems to practice:

  • Find All Duplicates
  • Find Corrupt Pair
  • First Missing Positive

Pattern #6: In-place Reversal of LinkedList

When to use: Problems requiring reversal of linked lists.

Key indicators:

  • "Reverse a linked list"
  • "Reverse every K-element sub-list"
  • "Rotate a linked list"

Template:

def reverse_linked_list(head):
    prev = None
    current = head

    while current:
        next_node = current.next  # Save next
        current.next = prev       # Reverse link
        prev = current            # Move prev forward
        current = next_node       # Move current forward

    return prev  # New head

Example problem: Reverse LinkedList

def reverse_list(head):
    """
    Reverse entire linked list.
    Time: O(n), Space: O(1)
    """
    prev = None
    current = head

    while current:
        # Save next node
        next_node = current.next

        # Reverse the link
        current.next = prev

        # Move pointers forward
        prev = current
        current = next_node

    return prev

Example problem: Reverse Sublist

def reverse_between(head, left, right):
    """
    Reverse sublist from position left to right.
    Time: O(n), Space: O(1)
    """
    if not head or left == right:
        return head

    dummy = ListNode(0)
    dummy.next = head
    prev = dummy

    # Move to start position
    for _ in range(left - 1):
        prev = prev.next

    # Reverse the sublist
    current = prev.next
    for _ in range(right - left):
        next_node = current.next
        current.next = next_node.next
        next_node.next = prev.next
        prev.next = next_node

    return dummy.next

More problems to practice:

  • Reverse Every K-element Sub-list
  • Rotate a LinkedList

Tree algorithms and traversal methods for interview problems

Pattern #7: Tree BFS (Breadth-First Search)

Breadth-First Search explores a tree level by level, like ripples spreading across water. It's perfect for problems that care about tree levels or need to find the shortest path in an unweighted tree.

When to use: Problems requiring level-order traversal of trees.

Key indicators:

Watch for these tree problem descriptions:

"Level order traversal" - Visit nodes level by level from top to bottom.

"Zigzag traversal" - Alternate direction for each level (left-to-right, then right-to-left).

"Minimum depth" - BFS finds the shortest path to a leaf node efficiently.

"Connect level order siblings" - Link nodes on the same level together.

Template:

from collections import deque

def level_order_traversal(root):
    if not root:
        return []

    result = []
    queue = deque([root])

    while queue:
        level_size = len(queue)
        current_level = []

        for _ in range(level_size):
            node = queue.popleft()
            current_level.append(node.val)

            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

        result.append(current_level)

    return result

More problems to practice:

  • Binary Tree Zigzag Level Order
  • Minimum Depth of Binary Tree
  • Right View of Binary Tree

Pattern #8: Tree DFS (Depth-First Search)

When to use: Tree problems requiring path traversal.

Key indicators:

  • "Path sum"
  • "All paths"
  • "Diameter of tree"
  • "Maximum depth"

Three traversal types:

def inorder(root):     # Left, Root, Right
    if not root:
        return []
    return inorder(root.left) + [root.val] + inorder(root.right)

def preorder(root):    # Root, Left, Right
    if not root:
        return []
    return [root.val] + preorder(root.left) + preorder(root.right)

def postorder(root):   # Left, Right, Root
    if not root:
        return []
    return postorder(root.left) + postorder(root.right) + [root.val]

Example problem: Path Sum

def has_path_sum(root, target_sum):
    """
    Check if tree has path with given sum.
    Time: O(n), Space: O(h) for recursion
    """
    if not root:
        return False

    # Leaf node - check if sum matches
    if not root.left and not root.right:
        return root.val == target_sum

    # Recursively check left and right subtrees
    remaining = target_sum - root.val
    return (has_path_sum(root.left, remaining) or
            has_path_sum(root.right, remaining))

More problems to practice:

  • All Paths for Sum
  • Sum of Path Numbers
  • Path With Maximum Sum

Pattern #9: Two Heaps

When to use: Problems involving finding median or scheduling.

Key indicators:

  • "Find median"
  • "Sliding window median"
  • "Maximize capital"

Template:

import heapq

class MedianFinder:
    def __init__(self):
        self.small = []  # Max heap (invert values)
        self.large = []  # Min heap

    def add_num(self, num):
        # Add to max heap (small)
        heapq.heappush(self.small, -num)

        # Balance: move largest from small to large
        heapq.heappush(self.large, -heapq.heappop(self.small))

        # If large has more elements, rebalance
        if len(self.large) > len(self.small):
            heapq.heappush(self.small, -heapq.heappop(self.large))

    def find_median(self):
        if len(self.small) > len(self.large):
            return -self.small[0]
        return (-self.small[0] + self.large[0]) / 2.0

More problems to practice:

  • Sliding Window Median
  • IPO (Maximize Capital)

Pattern #10: Modified Binary Search

When to use: Sorted or rotated arrays, finding ranges.

Key indicators:

  • "Search in sorted array"
  • "Find rotation point"
  • "Search in rotated array"
  • "Find range [start, end]"

Template:

def binary_search(arr, target):
    left, right = 0, len(arr) - 1

    while left <= right:
        mid = left + (right - left) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

Example problem: Search in Rotated Array

def search_rotated(nums, target):
    """
    Search in rotated sorted array.
    Time: O(log n), Space: O(1)
    """
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = left + (right - left) // 2

        if nums[mid] == target:
            return mid

        # Determine which half is sorted
        if nums[left] <= nums[mid]:
            # Left half is sorted
            if nums[left] <= target < nums[mid]:
                right = mid - 1
            else:
                left = mid + 1
        else:
            # Right half is sorted
            if nums[mid] < target <= nums[right]:
                left = mid + 1
            else:
                right = mid - 1

    return -1

# Test
print(search_rotated([4,5,6,7,0,1,2], 0))  # 4

More problems to practice:

  • Find Minimum in Rotated Array
  • Search Insert Position
  • Find Peak Element

Practice and mastery of algorithm patterns through coding exercises

How to Practice These Patterns

Learning patterns is just the first step. Mastery comes from deliberate, structured practice that builds both pattern recognition and implementation speed.

Week 1-2: Learn the Patterns

Start with the fundamentals—understanding beats memorization:

Study one pattern per day. Deep dive into the pattern's mechanics, when to use it, and common variations.

Understand the template. Don't just copy code—understand why each line exists and what problem it solves.

Solve 2-3 easy problems per pattern. Apply the template to simple problems until it feels natural.

Week 3-4: Practice Variations

  • Solve medium problems
  • Mix patterns (some problems use multiple patterns)
  • Time yourself

Week 5-6: Master Advanced Problems

  • Tackle hard problems
  • Do mock interviews
  • Review and optimize solutions

Daily Practice Routine

Day 1: Two Pointers (3 problems)
Day 2: Sliding Window (3 problems)
Day 3: Fast & Slow Pointers (3 problems)
Day 4: Review + Mock Interview
Day 5: Merge Intervals (3 problems)
Day 6: Cyclic Sort (3 problems)
Day 7: Rest or Review mistakes

Pattern recognition guide for identifying problem types

Pattern Recognition Cheatsheet

Use this quick reference during practice to identify which pattern applies to new problems. With time, pattern recognition becomes automatic.

If problem mentions... Consider pattern...
Sorted array/string Two Pointers, Binary Search
Pairs/triplets Two Pointers
Subarray/substring Sliding Window
Linked list cycle Fast & Slow Pointers
Overlapping intervals Merge Intervals
Numbers in range [1,n] Cyclic Sort
Reverse linked list In-place Reversal
Tree level order BFS
Tree paths DFS
Find median Two Heaps
Search in sorted Binary Search

AI-powered learning and practice with Interview Whisper

Using AI for Pattern Practice

Modern AI tools can accelerate your learning by providing instant feedback and guidance. It's like having a senior engineer mentor available 24/7.

Interview Whisper helps you:

Identify which pattern applies to a new problem. See a problem and not sure where to start? The AI can recognize the pattern instantly and point you in the right direction.

Suggest the right template when you're stuck. No need to flip through notes—get the relevant template with explanations on demand.

Point out optimization opportunities. Your brute-force solution works, but the AI can suggest how to optimize it from O(n²) to O(n).

Provide real-time hints during practice. Stuck on a specific step? Get contextual hints that help you learn without giving away the entire solution.

Example interaction:

You: "I need to find the longest substring without duplicates"
AI: "This is a Sliding Window pattern. Use two pointers and a set
     to track characters. Expand right, shrink left when duplicate found."

Conclusion

Instead of memorizing 500 individual problems, master these 10 patterns:

  1. ✅ Two Pointers - Pairs and triplets
  2. ✅ Sliding Window - Subarrays and substrings
  3. ✅ Fast & Slow Pointers - Cycles and middle elements
  4. ✅ Merge Intervals - Overlapping ranges
  5. ✅ Cyclic Sort - Numbers in given range
  6. ✅ In-place Reversal - LinkedList reversal
  7. ✅ Tree BFS - Level order traversal
  8. ✅ Tree DFS - Path problems
  9. ✅ Two Heaps - Find median
  10. ✅ Modified Binary Search - Sorted arrays

With these patterns, you'll recognize the approach for most interview problems within seconds.

Ready to practice with AI guidance? Download Interview Whisper for Windows and macOS and get real-time pattern recognition help during your coding practice. Our AI identifies patterns, suggests templates, and helps you think like a top-tier engineer.

Explore our pricing plans to unlock unlimited practice sessions and advanced features.


Related Articles:

Practice Resources:

Need help? Contact our support team for personalized guidance.

Found this helpful? Share it!

Ready to Ace Your Next Interview?

Get real-time AI coaching during your interviews with Interview Whisper

Download Free
Master 10 Essential Algorithm Patterns for Coding Interviews - Interview Whisper Blog | Interview Whisper