Conquer Coding Interviews: 15 LeetCode Patterns You Need
You just got that email – an interview invite for a Staff Software Engineer role at Google. Awesome. Now the panic sets in. You remember those coding interviews from five years ago. You survived, barely. This time, you want to nail it. You've heard the whispers, "It's all about patterns." They're not wrong. LeetCode isn't just about memorizing solutions; it's about recognizing underlying structures. I've been on both sides of that whiteboard, and trust me, knowing these fifteen patterns will fundamentally change how you approach problems.
Why Patterns, Not Just Problems?
Look, you can grind 500 LeetCode problems, or you can understand the 15-20 core algorithmic ideas that solve 80% of them. Which sounds more efficient for someone with a full-time job and a life? Interviewers don't want to see you regurgitate a solution. They want to see your thought process, your ability to break down a novel problem into familiar components. That’s what patterns give you. They're mental shortcuts, a framework for thinking when you're under pressure. You'll hear a problem, and instead of a blank stare, you'll think, "Ah, this smells like a Two Pointers problem," or "Dynamic Programming is probably the move here."
The Core 15: Your Interview Toolkit
Let's get into the specifics. These aren't obscure algorithms; they're the workhorses of competitive programming and, more importantly, everyday software development. I'm not giving you a single LeetCode problem per pattern here; I'm giving you the idea, the intuition, and a general scenario where it applies. You can find dozens of problems for each once you grasp the concept.
1. Two Pointers
This one's a classic for problems involving sorted arrays or lists. You typically have two pointers, one starting at the beginning (or a specific offset) and one at the end (or another offset), moving towards each other or in the same direction. It's fantastic for finding pairs, subarrays, or specific conditions that rely on relative positions. Think about reversing a string in-place, finding a pair with a given sum in a sorted array, or removing duplicates. It often reduces time complexity from O(N^2) to O(N).
2. Sliding Window
When you need to find a maximum, minimum, or average of a contiguous subarray or substring of a fixed or variable size, a sliding window is your best friend. Imagine a "window" that slides over the data. You expand the window by adding elements to one end and shrink it by removing elements from the other. This prevents re-calculating sums or counts for every possible subarray, which would be incredibly inefficient. Find the longest substring with K distinct characters, minimum window substring, or maximum sum subarray of a fixed size – all sliding window territory.
3. Fast & Slow Pointers (Hare & Tortoise)
Linked list problems often scream for this pattern. You have two pointers traversing the list at different speeds. The "fast" pointer moves two steps at a time, and the "slow" pointer moves one step. This setup is brilliant for detecting cycles, finding the middle of a linked list, or determining the start of a cycle. It's elegant and efficient, avoiding extra space for visited nodes.
4. Merge Intervals
This is for problems where you're given a list of intervals and need to find overlaps, merge them, or perform operations based on their relationships. The crucial first step is almost always sorting the intervals by their start times. Once sorted, you can iterate through and compare the current interval with the last merged interval. Merge overlapping intervals, insert a new interval, or find non-overlapping intervals – all these become straightforward with this approach.
5. Cyclic Sort
A bit more niche, but extremely useful for problems involving arrays containing numbers in a specific range (e.g., 1 to N) where you need to sort them or find missing/duplicate numbers. The idea is to place each number at its correct index. If you have an array of N numbers from 1 to N, the number i should be at index i-1. You iterate, and if a number isn't at its correct place, you swap it with the number that should be at its place. This is an in-place sort, usually O(N), which is better than comparison-based sorts. Find all missing numbers, find the duplicate number, or find the smallest missing positive number – this pattern shines.
6. In-Place Reversal of a Linked List
Don't allocate new nodes. Just reverse the pointers. This usually involves three pointers: previous, current, and next. You iterate through the list, changing the current node's next pointer to point to previous, then moving all three pointers one step forward. It's a fundamental linked list manipulation that often comes up in more complex problems, like reversing a sub-list or reversing every K nodes.
7. Tree Breadth-First Search (BFS)
Level-order traversal, finding the shortest path in an unweighted graph, or checking if a tree is complete. BFS uses a queue to visit nodes level by level. You add the root to the queue, then loop: dequeue a node, process it, and enqueue its children. This systematic exploration ensures you hit all nodes at a given depth before moving to the next. It's your go-to for anything requiring exploration by levels.
8. Tree Depth-First Search (DFS)
Recursion is usually the heart of DFS. Think about pre-order, in-order, and post-order traversals. DFS explores as far as possible along each branch before backtracking. It's perfect for problems where you need to visit every node, calculate height, check for symmetry, or find paths from root to leaf. It can be implemented recursively or iteratively with an explicit stack. Balancing a binary tree, finding the maximum path sum, or checking if two trees are identical are classic DFS applications.
9. Two Heaps
This pattern is a bit more advanced but incredibly powerful for problems where you need to maintain order or find median-like values in a stream of data. You typically use a min-heap and a max-heap. The max-heap stores the smaller half of the numbers, and the min-heap stores the larger half. By keeping them balanced (same size or differing by one), the median or a similar statistic can be found efficiently (O(1) after O(log N) insertion). Finding the median of a number stream or scheduling tasks with minimum delay are prime examples.
10. Subsets (Backtracking)
Generating all possible subsets or combinations of a given set of elements. This is a classic backtracking problem. You typically use recursion: at each step, you have two choices – either include the current element in your subset or don't. You explore both paths and then backtrack. This pattern extends to permutations, combinations, and problems with constraints like "subsets with duplicates" or "subsets with a specific sum."
11. Modified Binary Search
Binary search isn't just for finding an exact element in a sorted array. It's a general technique for problems where the search space can be repeatedly halved. Think about finding the ceiling of a number, searching in a rotated sorted array, or finding the peak element. The modification comes in how you adjust your low and high pointers based on the comparison, not just for equality, but for satisfying a condition. It’s a powerful O(log N) primitive.
12. Top 'K' Elements (Heaps)
When you need to find the K smallest, K largest, K most frequent, or K anything from a collection, a heap (priority queue) is usually the answer. For "K smallest," use a max-heap of size K. For "K largest," use a min-heap of size K. As you iterate through the data, you add elements to the heap. If the heap size exceeds K, you pop the root. This keeps the heap always containing the K elements that satisfy your criteria. Find the Kth largest number, top K frequent elements, or K closest points to the origin.
13. K-way Merge
This pattern comes up when you have K sorted lists and you need to merge them into a single sorted list, or find the Kth smallest element among all of them. A min-heap is almost always the solution. You initially add the first element of each list to the min-heap. Then, you repeatedly extract the smallest element from the heap, add it to your result, and if the extracted element has a "next" element in its original list, you add that to the heap. This ensures you're always considering the globally smallest available element. Merge K sorted lists or find the Kth smallest number in M sorted lists.
14. Topological Sort (Graphs)
When you have directed acyclic graphs (DAGs) and need to process nodes in a specific order such that for every directed edge U -> V, node U comes before node V in the ordering. This is crucial for dependency resolution. Think about course scheduling, task dependencies in a build system, or compilation order. Kahn's algorithm (using a queue and in-degrees) or DFS-based approaches are common. Detecting cycles in a directed graph is often a byproduct of trying to perform a topological sort.
15. Dynamic Programming
Ah, DP. The one that makes everyone sweat. This isn't a single algorithm but a technique for solving problems by breaking them down into simpler overlapping subproblems and storing the results of those subproblems to avoid re-computation. It's about recognizing optimal substructure. If you find yourself solving the same subproblem repeatedly with recursion, that's often a sign for DP. Classic problems include Fibonacci sequence, knapsack, longest common subsequence, and coin change. The trick is defining the state and the recurrence relation, then figuring out if you need memoization (top-down) or tabulation (bottom-up). It's challenging because it requires deep insight into the problem's structure. You'll spend more time thinking about the recurrence than coding it.
Your Study Strategy: More Than Just Coding
Just reading this list won't make you an interview wizard. You need to apply these.
First, understand the intuition behind each pattern. Why does it work? What are its limitations? When would you not use it?
Then, solve a foundational problem for each pattern. Don't just look at the solution. Try it yourself. Fail. Debug. Understand why you failed.
Next, solve variations. How does the problem change if there are duplicates? What if the input is a linked list instead of an array? This forces you to adapt the pattern.
Don't get stuck on one problem for too long. If you're spinning your wheels for more than 45 minutes, check a hint, or look at the solution. The goal isn't to be a hero; it's to learn. Then, implement it yourself without looking. Repeat this process until you can implement it cleanly and explain your thought process.
The Caveat: Not Every Problem Fits Nicely
Here's the honest truth: not every interview problem will neatly fit into one of these fifteen boxes. Some are combinations, some are entirely novel, and some are just plain weird. This list covers the high-frequency patterns. If you're aiming for a Principal Engineer role, expect discussions on system design, distributed systems, and architectural trade-offs to be just as, if not more, critical than a LeetCode problem. For Staff and Senior roles, these patterns are a strong foundation, but behavioral questions and your ability to communicate complex ideas are equally important. Your mileage will absolutely vary based on the company, the specific team, and even the interviewer's mood that day. Prepare broadly, but focus your initial effort here.
Why This Works (and What Doesn't)
What works is deliberate practice. Coding for 4 hours without a plan is less effective than 1 hour with a structured approach focused on patterns. What doesn't work is blindly memorizing solutions. Interviewers can spot that a mile away. They'll ask follow-up questions that probe your understanding, and if you just memorized, you'll crumble.
These patterns are your mental scaffolding. When a problem comes up, you'll mentally run through this checklist: "Is this a two-pointer problem? A sliding window? Does it look like a tree traversal?" This structured thinking saves you precious time and reduces anxiety during the interview. You're not starting from scratch; you're starting from a known good approach.
Beyond the Algorithm: Communication is Key
Even with these patterns mastered, you still need to communicate your process effectively. Talk through your initial thoughts, your chosen pattern, the time and space complexity, and any edge cases you're considering. Write clean, readable code. Test it with examples. This isn't just about correctness; it's about demonstrating your ability to be a productive member of a team. Nobody wants to work with a brilliant coder who can't explain their logic.
Focus on these patterns, practice consistently, and articulate your solutions clearly. You'll be surprised how much more confident and effective you become in those high-stakes interview rooms. Good luck.
Ready to Ace Your Next Interview? Practice with AI-powered mock interviews tailored to your target role and company. Start Practicing for Free | Explore Interview Prep
Ready to Ace Your Next Interview?
Practice with AI-powered mock interviews tailored to your target role and company. Start Practicing for Free | Explore Interview Prep
