← Back to list

LeetCode Gets Easier Once You Recognize These 15 Coding Patterns

Stop memorizing solutions. Learn how to identify the structure hiding inside unfamiliar interview problems.

Neha Gupta in JavaScript in Plain English · 2026-07-06 15:56 · 131 claps · 6.7 min read paywalled
#dsa-courses #javascript #data-structure-algorithm #data-structures #coding
Open on Medium ↗
Wiki topics: 💻 · Programming 🌐 · Web Development

LeetCode Gets Easier Once You Recognize These 15 Coding Patterns

Stop memorizing solutions. Learn how to identify the structure hiding inside unfamiliar interview problems.

Image Thumbnail — LeetCode Gets Easier Once You Recognize These 15 Coding Patterns

Image Thumbnail — LeetCode Gets Easier Once You Recognize These 15 Coding Patterns

For a long time, I thought improving at LeetCode meant solving more questions.

So I solved arrays. Then strings. Then linked lists. A week later, I would open a similar problem and still have no idea where to begin.

The problem was not that I had forgotten the code.

I had never learned what the code represented.

Most coding interview questions are not completely new problems. They are familiar structures disguised with different stories, constraints, and variable names.

Once I started identifying those structures, something changed. I no longer asked:

“Have I solved this exact question before?”

I started asking:

“Which pattern does this problem resemble?”

That question is far more useful.

Image- Unfamiliar Problem → Identify Pattern → Apply Template → Adjust Edge Cases

Image- Unfamiliar Problem → Identify Pattern → Apply Template → Adjust Edge Cases

Why Random Problem-Solving Stops Working

Solving random questions can improve syntax and implementation speed. But it does not always improve problem recognition.

You might solve 100 questions and remember 20 solutions.

Or you might learn 15 patterns and use them across hundreds of variations.

The second approach scales better.

Here are the patterns I would prioritize.

Image: Patterns vs Common Signal

Image: Patterns vs Common Signal

1. Prefix Sum: Stop Recalculating the Same Range

Suppose an API receives several requests asking for the sum of values between two positions.

The direct solution loops through the requested range every time. That is acceptable for one query. It becomes wasteful for thousands.

A prefix sum array stores the cumulative total up to each index.

function buildPrefixSum(nums) {
    const prefix = new Array(nums.length + 1).fill(0);
  for (let i = 0; i < nums.length; i++) {
        prefix[i + 1] = prefix[i] + nums[i];
    }
    return prefix;
}
function rangeSum(prefix, left, right) {
    return prefix[right + 1] - prefix[left];
}

The extra leading zero removes the awkward left - 1 boundary check.

That small implementation choice matters. Most prefix-sum bugs are not conceptual. They are indexing bugs.

Use this pattern when you see:

  • Multiple range-sum queries
  • Subarrays with a target sum
  • Cumulative frequencies
  • Balance calculations between two regions

2. Two Pointers: Remove Unnecessary Comparisons

Two pointers work well when the search space has direction.

For example, checking whether a string is a palindrome does not require creating a reversed copy.

function isPalindrome(text) {
    let left = 0;
    let right = text.length - 1;
    while (left < right) {
        if (text[left] !== text[right]) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

The important part is not having two variables.

The important part is knowing why one pointer moves instead of the other.

That same reasoning appears in:

  • Pair sum in a sorted array
  • Removing duplicates
  • Container With Most Water
  • Partitioning arrays
  • Merging sorted collections

A common mistake is trying two pointers on an unsorted array without checking whether sorting would destroy information such as original indices.

3. Sliding Window: Reuse the Work You Already Did

At first, I treated every subarray as a separate calculation.

That leads to repeated work because adjacent windows share most of their elements.

For a fixed window of size k, subtract the element leaving the window and add the new element entering it.

function maxWindowSum(nums, k) {
    if (k > nums.length) return null;
    let windowSum = 0;
    for (let i = 0; i < k; i++) {
        windowSum += nums[i];
    }
    let maxSum = windowSum;
    for (let right = k; right < nums.length; right++) {
        windowSum += nums[right];
        windowSum -= nums[right - k];
        maxSum = Math.max(maxSum, windowSum);
    }
    return maxSum;
}

This changes an O(n × k) solution into O(n).

Variable-size windows are harder. They require a rule that tells you when to shrink the left side.

Use sliding window when the problem mentions:

  • Longest or shortest substring
  • Contiguous elements
  • At most or exactly k
  • Frequency constraints inside a range

Image: Sliding window workflow

Image: Sliding window workflow

4. Fast and Slow Pointers

This pattern is commonly associated with linked-list cycles, but its usefulness goes beyond that.

Move one pointer one step and another pointer two steps.

You can use it to:

  • Detect a cycle
  • Find the middle of a linked list
  • Locate the start of a cycle
  • Identify repeated state transitions

The surprising part is that cycle detection does not require storing every visited node.

That saves O(n) space.

5. In-Place Linked-List Reversal

Linked-list problems become easier when you stop focusing on node values and start drawing arrows.

For reversal, three references are enough:

  • previous
  • current
  • next

The critical step is saving current.next before changing it. Forget that, and the remaining list becomes unreachable.

This pattern appears in reversing sublists, rearranging nodes, palindrome checks, and reversing nodes in groups.

6. Monotonic Stack

When a problem asks for the next greater, next smaller, previous greater, or previous smaller element, a nested loop is usually the first solution.

A monotonic stack avoids scanning the same elements repeatedly.

Each index is pushed once and popped at most once, making the total complexity O(n).

Typical problems include:

  • Daily Temperatures
  • Largest Rectangle in a Histogram
  • Stock Span
  • Next Greater Element

The stack is not kept sorted for presentation. Its order preserves unresolved candidates.

7. Top K Elements

Sorting everything to retrieve five values is often unnecessary.

For the k largest elements, maintain a min-heap of size k. The smallest item in the heap is the weakest member of the current top group.

This produces O(n log k) time instead of O(n log n).

However, heaps are not always the best answer. Quickselect offers average O(n) time when you only need the kth element, although its worst case and implementation complexity deserve consideration.

8. Overlapping Intervals

Interval problems usually become manageable after sorting by start time.

Then compare the current interval with the last merged interval:

  • Overlap: extend the ending boundary
  • No overlap: start a new merged interval

This pattern appears in meeting rooms, booking conflicts, calendar merging, scheduling, and range insertion.

The main bug to watch for is whether touching intervals such as [1, 3] and [3, 5] should be considered overlapping. The problem statement decides that.

9. Modified Binary Search

Binary search is not limited to finding an element in a perfectly sorted array.

It also works when you can eliminate half of a search space based on a condition.

Examples include:

  • Rotated sorted arrays
  • First and last occurrence
  • Peak elements
  • Square root
  • Minimum feasible capacity
  • Search on the answer

This is where things get interesting: many binary-search problems do not search an array. They search a range of possible answers.

10–15. The Patterns That Build Larger Solutions

The remaining patterns often combine with one another:

Binary Tree Traversal

Choose traversal based on processing order:

  • Inorder for sorted BST values
  • Preorder for copying or serialization
  • Postorder when children must be processed first
  • Level order for layer-by-layer processing

Depth-First Search

Use DFS when you need to explore complete paths, connected components, cycles, or recursive decision branches.

Breadth-First Search

Use BFS for level-order exploration and shortest paths in unweighted graphs.

Matrix Traversal

Treat each valid cell as a graph node and its reachable neighbours as edges.

Backtracking

Make a choice, explore it, undo it, and try another choice.

That “undo” step is what beginners most often miss.

Dynamic Programming

DP becomes relevant when recursion repeatedly solves the same state.

The hard part is rarely writing the table. It is defining what each state means.

Image: DP workflow

Image: DP workflow

Common Mistakes While Learning Patterns

Do not memorize one code template and force it onto every problem.

Instead, ask:

  1. What part of the problem repeats?
  2. What information must I preserve?
  3. Can one decision eliminate several possibilities?
  4. Is the problem asking about a contiguous region?
  5. Am I exploring paths, levels, ranges, or states?

Patterns are starting points, not final solutions.

Constraints, duplicate values, negative numbers, mutation rules, and output requirements can change the implementation.

What Changed After I Started Thinking in Patterns

The biggest improvement was not faster coding.

It was faster rejection of bad approaches.

I could recognize when a nested loop was repeating work, when a queue was more suitable than recursion, or when sorting would simplify the problem but destroy original indices.

That was the unexpected payoff.

Pattern knowledge does not only help you find the correct solution. It helps you stop investing time in the wrong one.

Final Takeaways

You do not need to solve every LeetCode problem.

You need to understand the structures that repeatedly appear inside them.

Start with:

  • Prefix Sum
  • Two Pointers
  • Sliding Window
  • Fast and Slow Pointers
  • Monotonic Stack
  • Heap
  • Binary Search
  • DFS and BFS
  • Backtracking
  • Dynamic Programming

For each pattern, solve a few variations and write down:

  • The signal that suggested the pattern
  • The invariant maintained by the algorithm
  • The reason each pointer, state, or data structure changes
  • The edge case that broke your first attempt

The goal is not to remember more solutions.

It is to need fewer of them.

I am providing a pattern recognition sheet. If you’re looking for serious learning, You can comment “Sheet”. I’ll share with you.

From Dev Simplified

  • 👏 Enjoyed the article? Don’t forget to leave a clap.
  • 💬 Have thoughts or questions? Share them in the comments.
  • ✍️ Want to write for Dev Simplified? Drop a personal note on any Dev Simplified story with your draft link.

Thousands of developers share what they’re building, learning, and discovering across our publications every month. One account connects you to our entire network of publications and communities. **Explore more at plainenglish.io.**


메타데이터
post_id
71d796d7e493
slug
leetcode-gets-easier-once-you-recognize-these-15-coding-patterns-71d796d7e493
url
https://javascript.plainenglish.io/leetcode-gets-easier-once-you-recognize-these-15-coding-patterns-71d796d7e493
canonical_url
https://javascript.plainenglish.io/leetcode-gets-easier-once-you-recognize-these-15-coding-patterns-71d796d7e493
author_url
https://medium.com/@techbynehagupta
status
ok
fetched_at
2026-07-08 20:12:56