Top 15 LeetCode Problems for Backend Engineer Interviews

- Graphs dominate backend loops: Course Schedule II, Network Delay Time, Critical Connections, and Number of Islands map directly to dependency resolution, routing, and failure detection
- LRU Cache (LC 146) is the single most-asked backend coding question; know the doubly linked list plus hash map implementation cold
- Two-heap pattern (Find Median from Data Stream) models P50/P99 latency tracking; the balancing step is the only tricky part
- Monotonic deque (Sliding Window Maximum) and two-pointer window (Minimum Window Substring) cover the stream processing patterns common in observability and metrics pipelines
- Union-Find (Accounts Merge) and binary search on sorted maps (Time Based Key-Value Store) are backend-specific data structure questions that rarely appear in frontend loops
- Prep in pattern order: graph section first, then heaps, then sliding window; budget 40% of prep time on graphs and design problems
Most "top LeetCode problems" lists just repackage the Blind 75. Someone took the original spreadsheet, changed the formatting, and published it as a new article. The problem is that this treats every engineering role the same. Backend is different. Graphs come up more. Design-flavored data structure problems are nearly universal. The problems that look abstract on LeetCode map directly to real backend work: dependency resolution, task scheduling, log aggregation, cache eviction, network routing.
This guide covers the 15 LeetCode problems for backend engineer interviews that show up most consistently across loops at Google, Meta, Amazon, Stripe, and Datadog. For each: what pattern it tests, why backend interviewers care about it, and the one thing that trips candidates up.
The Pattern Map
| # | Problem | LC # | Pattern | Difficulty |
|---|---|---|---|---|
| 1 | LRU Cache | 146 | Hash Map + Doubly Linked List | Medium |
| 2 | Course Schedule II | 210 | Topological Sort (Kahn's) | Medium |
| 3 | Task Scheduler | 621 | Greedy + Frequency Heap | Medium |
| 4 | Find Median from Data Stream | 295 | Two Heaps | Hard |
| 5 | Sliding Window Maximum | 239 | Monotonic Deque | Hard |
| 6 | Minimum Window Substring | 76 | Sliding Window + Freq Map | Hard |
| 7 | Merge k Sorted Lists | 23 | K-Way Merge (Min-Heap) | Hard |
| 8 | Network Delay Time | 743 | Dijkstra's Algorithm | Medium |
| 9 | Number of Islands | 200 | BFS/DFS on Grid | Medium |
| 10 | Word Ladder | 127 | BFS on Implicit Graph | Hard |
| 11 | Top K Frequent Elements | 347 | Heap + Hash Map | Medium |
| 12 | Longest Consecutive Sequence | 128 | Hash Set | Medium |
| 13 | Time Based Key-Value Store | 981 | Binary Search on Sorted Map | Medium |
| 14 | Critical Connections in a Network | 1192 | Tarjan's Bridges | Hard |
| 15 | Accounts Merge | 721 | Union-Find | Medium |
Your Backend Servers Are Just Graphs
Backend systems are graphs. Services depend on other services. Tasks have prerequisites. Network packets route through nodes. Backend interviewers know this, so they skew heavily toward graph problems in a way frontend loops rarely do. If you've been skipping graph problems because "they don't come up," you've been preparing for the wrong interview.
1. Number of Islands (LC 200)
The warm-up graph problem. Every backend interviewer has asked it or a variant of it at least once. The trap isn't the BFS/DFS itself, it's the outer loop. You need to iterate over every cell and trigger a traversal on any '1' you haven't visited yet. Candidates who forget the outer loop get one connected component and an awkward silence where feedback normally lives.
2. Course Schedule II (LC 210)
Return the topological ordering of courses given prerequisites, or empty if a cycle exists. This is exactly dependency resolution. Build systems, package managers, microservice startup order all have a DAG of dependencies somewhere underneath. npm knows this. Gradle knows this. Your interviewer knows this.
Use Kahn's algorithm: track in-degrees, initialize a queue with all zero-in-degree nodes, process one at a time. If your output length is less than n, there's a cycle.
def findOrder(numCourses, prerequisites): graph = [[] for _ in range(numCourses)] in_degree = [0] * numCourses for course, pre in prerequisites: graph[pre].append(course) in_degree[course] += 1 queue = deque([i for i in range(numCourses) if in_degree[i] == 0]) order = [] while queue: node = queue.popleft() order.append(node) for neighbor in graph[node]: in_degree[neighbor] -= 1 if in_degree[neighbor] == 0: queue.append(neighbor) return order if len(order) == numCourses else []
Cycle detection trick: processed_count != n after the loop means a cycle exists. Simpler than tracking a visited set. The topological sort guide covers both Kahn's and the DFS variant.
3. Word Ladder (LC 127)
Find the shortest transformation sequence from beginWord to endWord, changing one letter at a time. The insight: this is BFS on an implicit graph where each word is a node. You don't build the graph upfront. You generate neighbors on the fly by trying every single-character substitution.
Performance trap: if candidate in wordSet is O(1). if candidate in wordList on a list is O(n). Convert it first. You will forget this at 11pm the night before your interview. Convert it first anyway.
4. Network Delay Time (LC 743)
Given a directed weighted graph and a source node, find the minimum time for all nodes to receive a signal. Classic Dijkstra's. The answer is max(dist.values()) once all nodes are reached. If any node is unreachable, return -1.
Datadog and observability companies love this one because it directly models latency budgets and network routing. See the Dijkstra's algorithm guide for the lazy-deletion heap pattern used in practice.
5. Critical Connections in a Network (LC 1192)
Find every bridge in an undirected graph: edges whose removal disconnects the network. A bridge exists when low[v] > disc[u] for a tree edge u -> v, meaning no back edge reaches above u from v's subtree.
This is Tarjan's bridge-finding algorithm. It's hard, but it comes up at infrastructure-heavy companies because identifying single points of failure in a service topology is an actual job. Use edge indices instead of parent-vertex skipping to handle multigraphs correctly. If this feels like more graph theory than you wanted in a coding interview, wait until you're debugging a network partition at 2am.
Cache and Design Problems: The Section Frontend Loops Skip
These almost never appear in frontend loops. Backend interviewers use them to test whether you understand the data structures running under real systems. Not the theory. The actual implementation you'd write for a production cache.
6. LRU Cache (LC 146)
Implement a cache with O(1) get and O(1) put, evicting the least recently used entry when capacity is exceeded. The solution is a doubly linked list plus a hash map. The map gives O(1) lookup; the list maintains recency order and allows O(1) removal anywhere via direct pointer.
This is the most-asked backend coding question across companies. Know both the scratch implementation and Python's OrderedDict shortcut for the follow-up. See the full LRU Cache guide for the sentinel-node trick that eliminates edge cases.
7. Time Based Key-Value Store (LC 981)
Design a key-value store that keeps multiple timestamped values per key and returns the most recent value at or before a given timestamp. get is binary search: find the rightmost timestamp ≤ the query.
This is MVCC in miniature. The problem tests whether you instinctively reach for binary search when data is sorted. Versioned stores like etcd and RocksDB use this structure constantly. The candidates who reach for a linear scan here are the ones who skipped the binary search guide.
Heap Problems: Scheduling, Merging, Monitoring
Priority queues run backend systems. Job queues, task schedulers, top-N analytics, log mergers. This section tests whether you reach for a heap before you reach for a sort. You should always reach for a heap before you reach for a sort, unless you need all elements ordered. Sorting to find the top 1 element is like hiring a moving company to find your keys.
8. Task Scheduler (LC 621)
Given tasks and a cooldown period n, find the minimum intervals to finish all tasks. The greedy insight: always schedule the most frequent remaining task next. Use a max-heap keyed on frequency. When no task is available due to cooldown, idle.
This is job queue scheduling with resource constraints. Which is exactly what a distributed task scheduler does, before the team rewrites it twice and someone ports it to Temporal.
9. Find Median from Data Stream (LC 295)
Maintain a running median as numbers arrive. Two heaps: a max-heap for the lower half, a min-heap for the upper half. Keep them balanced (sizes differ by at most 1). The median is either the top of the larger heap or the average of both tops.
P50/P99 latency tracking works like this. The pattern is clean once you see it. The balancing step is the only part that trips candidates, and it trips almost everyone the first time.
10. Merge k Sorted Lists (LC 23)
Merge k sorted linked lists into one. Naive approach: merge pairwise. Optimal: min-heap of size k holding the current head of each list. Pop the minimum, advance that list, push the new head.
O(N log k) where N is total nodes. This pattern runs inside every distributed merge pipeline: log aggregation, sorted result merging, the merge phase of an external sort.
11. Top K Frequent Elements (LC 347)
Return the k most frequent elements. Frequency map first, then a min-heap of size k. Push each element; if the heap exceeds size k, pop the minimum-frequency element.
Nearly every backend observability system runs this query constantly: "top N error codes," "most accessed endpoints," "highest-latency operations." Every metrics pipeline does some version of this.
Sliding Window: Stream Processing
Backend systems process streams. Metrics pipelines, log parsers, rate limiters. The sliding window pattern models a moving observation window over a time series. Two problems in this category are worth knowing cold.
12. Sliding Window Maximum (LC 239)
Find the maximum value in every window of size k. The optimal solution is a monotonic deque: maintain a deque of indices in decreasing order of value. The front is always the current maximum. Pop from the back when a new element is larger; pop from the front when an index falls outside the window.
def maxSlidingWindow(nums, k): dq = deque() # stores indices, decreasing by value result = [] for i, num in enumerate(nums): while dq and nums[dq[-1]] <= num: dq.pop() dq.append(i) if dq[0] <= i - k: dq.popleft() if i >= k - 1: result.append(nums[dq[0]]) return result
13. Minimum Window Substring (LC 76)
Find the shortest substring of s containing all characters of t. Two pointers with a frequency map: expand right until you have all required characters, shrink left to find the minimum valid window.
Hard problem, but the pattern generalizes across log parsing and event-span detection. Worth knowing cold.
Hash Patterns: Data Normalization
14. Longest Consecutive Sequence (LC 128)
Find the longest consecutive integer sequence in an unsorted array. The O(n) trick: put everything in a set, then only start counting from the beginning of a sequence (where num - 1 is not in the set). This avoids redundant traversal and makes the problem linear.
The problem looks like it wants a sort. It doesn't want a sort. Use case: gap detection in ID sequences, partition validation, data normalization.
15. Accounts Merge (LC 721)
Given accounts with a name and a list of emails, merge accounts that share any email. Use Union-Find: each email is a node, each account's emails get unioned together. Group by root to reconstruct merged accounts.
This exact problem runs in every user deduplication pipeline. The pattern generalizes: Union-Find over non-integer elements via a node-to-id map. See the Union-Find algorithm guide for the path-compression implementation.
How to Actually Prep These Problems
Work through them in pattern order, not problem order. Start with Number of Islands (grid BFS/DFS), then Course Schedule II (topological sort), then Network Delay Time (Dijkstra). The graph section builds on itself. Then do the heap section as a unit. Then sliding window.
The backend-specific emphasis is graphs and design problems. If you've been skipping graph problems because "they don't come up," budget 40% of your prep time on the graph and design sections and recalibrate.
For each problem, practice explaining your approach out loud before you code. Backend interviewers evaluate whether you can reason about a system the way a senior engineer does. The code is evidence. The explanation is the test. Most candidates skip the out-loud practice because it feels awkward sitting alone narrating to nobody. The fix is simple. Just narrate.
SpaceComplexity runs voice-based mock interviews where you narrate your approach in real time and get rubric-based feedback on communication, not just correctness. That's the gap most candidates miss when prepping from a problem list alone.
Further Reading
- Topological Sorting - Wikipedia
- Dijkstra's Algorithm - Wikipedia
- Bridge (Graph Theory) - Wikipedia
- Disjoint-Set Data Structure - Wikipedia
- Heap Data Structure - Wikipedia