Top 15 LeetCode Problems for Full-Stack Engineer Interviews

- Full-stack rounds favor mediums that mirror real product work: DOM trees, scheduling, dependency resolution, and client-side caches, not hard DP.
- Trees appear most often: Max Depth, Level Order Traversal, and Validate BST cover the warm-up category at Apple, Meta, and Google.
- Course Schedule is mandatory: topological sort maps directly to Webpack dependency resolution, CI/CD pipelines, and package managers.
- LRU Cache is the one design problem that consistently shows up and requires fusing a hash map with a doubly linked list for O(1) get and put.
- Merge Intervals and Meeting Rooms II teach concurrent resource allocation, the scheduling logic behind thread pools and connection limits.
- The mistake log beats re-reading solutions: write down the exact wrong line per problem and review only that before the interview.
- Pattern transfer is the actual skill: articulate what each problem group shares before moving to the next one.
Full-stack interviews are not a shorter backend loop. They are calibrated differently. The algorithmic bar is lower, but the problem selection is deliberate: every LeetCode problem on this list maps to something a full-stack engineer actually touches in production. Scheduling, caching, dependency resolution, DOM traversal.
Skip the hard DP. Learn these 15 instead.
Full-Stack LeetCode Rounds Hit Different
Most full-stack loops run 45-minute rounds at medium difficulty. Hard problems appear sometimes, usually at FAANG, but they are the exception. What you almost always see are mediums that connect directly to real product engineering work.
The distribution skews heavily toward trees, hash maps, and interval problems because those structures underpin UI hierarchies, client-side caches, and scheduling systems. Graph problems show up because dependency graphs are everywhere: build tooling, course prerequisites, package managers. You will rarely see Dijkstra. You will definitely see topological sort.
Knowing the underlying pattern is what lets you translate.
Quick Reference
| # | Problem | Difficulty | Pattern |
|---|---|---|---|
| 1 | Two Sum | Easy | Hash Map |
| 2 | Group Anagrams | Medium | Hash Map + String |
| 3 | Longest Substring Without Repeating Characters | Medium | Sliding Window |
| 4 | Valid Parentheses | Easy | Stack |
| 5 | Decode String | Medium | Stack + Recursion |
| 6 | Maximum Depth of Binary Tree | Easy | DFS |
| 7 | Binary Tree Level Order Traversal | Medium | BFS |
| 8 | Validate Binary Search Tree | Medium | DFS + Range |
| 9 | Number of Islands | Medium | BFS/DFS on Grid |
| 10 | Course Schedule | Medium | Topological Sort |
| 11 | LRU Cache | Medium | Hash Map + Doubly Linked List |
| 12 | Merge Intervals | Medium | Sort + Scan |
| 13 | Meeting Rooms II | Medium | Heap / Sweep Line |
| 14 | Linked List Cycle | Easy | Fast + Slow Pointer |
| 15 | Kth Largest Element in an Array | Medium | Heap / Quickselect |
11 mediums, 3 easies, 0 hards.
Hash Maps and Sliding Windows
1. Two Sum (LC 1)
Every interview loop contains Two Sum. Every single one. It is the universe's way of asking whether you reach for a hash map or write a nested loop that makes the interviewer silently update your scorecard.
The unspoken test is clarifying questions. Are there duplicates? Can the same element be used twice? Say it out loud before you write a line. This is a warmup problem. You should be done in under five minutes and onto the follow-up.
2. Group Anagrams (LC 49)
Given a list of strings, group the anagrams together. Sort each string to get its canonical key, then accumulate strings in a hash map keyed by that sorted form.
This shows up at Airbnb, Meta, and Stripe and tests whether you can identify a grouping key. That skill transfers directly to any problem where you partition data by some derived property.
from collections import defaultdict def group_anagrams(strs): groups = defaultdict(list) for s in strs: groups[tuple(sorted(s))].append(s) return list(groups.values())
3. Longest Substring Without Repeating Characters (LC 3)
Classic sliding window. Maintain a set of characters in the current window. Hit a duplicate, shrink from the left until it is gone, then expand right.
The gotcha: you need the character's last-seen index to shrink efficiently, not just a membership set. Hash map over set. The candidates who get this wrong almost always built a set first and then wondered why they had to add a second pass.
When You See Nesting, Think Stack
4. Valid Parentheses (LC 20)
Push opening brackets onto a stack. When you see a closing bracket, check whether it matches the top. Stack not empty at the end? Also invalid.
Every full-stack engineer should be able to do this in under ten minutes. If you cannot, stop reading this post and go practice it right now. HTML validation, expression parsing, template engines, JSON verification: the stack-matching pattern is everywhere. It will show up in your interview. Probably twice.
Edge case: a single closing bracket on an empty stack returns false immediately.
5. Decode String (LC 394)
Given "3[a2[bc]]", return "abcbcabcbcabcbc". The trick is a stack that holds the partial string and its repetition count as you descend into nested brackets. A recursive approach processes one bracket level per call.
This tests your ability to handle nested structure. Deeply nested configs, template strings, recursive UI components: the problem is a paper version of those. Know both approaches. The interviewer will ask for the other one.
The DOM Is a Tree. So Is Everything Else.
The DOM is a tree. React's component hierarchy is a tree. JSON with nested objects is a tree. Every tree problem you solve is practice for reasoning about UI structure. Apple and Meta use tree problems specifically to probe how you think about component rendering and traversal.
And yet engineers who write React all day will blank when asked to traverse a binary tree. The two feel different. They are not.

Full-stack engineering: fluent in components, still sobbing at BST validation
6. Maximum Depth of Binary Tree (LC 104)
DFS recursion: the depth of a node is one plus the max depth of its two children. Base case: null returns 0.
This is often the first question in a tree section. If you cannot do it cleanly in three lines, every harder tree problem on this list will be rough.
7. Binary Tree Level Order Traversal (LC 102)
BFS with a queue. The trick: snapshot the queue length at the start of each level, then process exactly that many nodes before moving to the next iteration.
from collections import deque def level_order(root): if not root: return [] result, queue = [], deque([root]) while queue: level = [] for _ in range(len(queue)): node = queue.popleft() level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level) return result
The for _ in range(len(queue)) snapshot is the whole key. This pattern appears in every level-by-level tree problem. Burn it in.
8. Validate Binary Search Tree (LC 98)
The wrong approach: check that each node is greater than its left child and less than its right child. That fails when a left subtree node violates the root's constraint.
The correct approach: propagate a valid range down. Each node must fall in (min_val, max_val). Go left, tighten the max. Go right, tighten the min.
def is_valid_bst(root, lo=float('-inf'), hi=float('inf')): if not root: return True if not (lo < root.val < hi): return False return is_valid_bst(root.left, lo, root.val) and \ is_valid_bst(root.right, root.val, hi)
This problem kills candidates who think parent-only comparison is enough. The wrong approach looks completely reasonable until it doesn't work. Which is exactly why they ask it.
Dependencies Are Graphs
9. Number of Islands (LC 200)
Given a 2D grid of '1' (land) and '0' (water), count distinct islands. DFS or BFS from each unvisited land cell, marking cells visited as you go. Increment the count each time you start a new traversal.
The most universally asked graph problem. Appears at Meta, Google, Amazon, LinkedIn. The outer loop is not optional. Without it, you miss islands unreachable from the first starting cell. That is the most common bug. Write the outer loop first.
10. Course Schedule (LC 207)
Given prerequisite pairs, determine whether all courses can be finished. Cycle detection in a directed graph. Use Kahn's algorithm (topological sort via BFS) or DFS with three-color visited state.
The clearest production analog on this list. Webpack dependency resolution, CI/CD pipelines, package managers: all solve this problem. Validity check: if processed count is less than total nodes, a cycle exists. That one line is the whole test.
The One Design Problem That Matters
11. LRU Cache (LC 146)
Design a cache that evicts the least recently used item when full. O(1) get, O(1) put.
This requires combining a hash map with a doubly linked list. The hash map gives O(1) lookup. The linked list maintains insertion order and supports O(1) removal from any position because you hold a direct pointer to the node. Sentinel head and tail nodes eliminate boundary condition bugs.
Client-side caches, HTTP response caches, in-memory session stores: all variants of this. The problem is asking whether you can design a data structure under constraints. See the full walkthrough at /blog/lru-cache-implementation.
Scheduling Is Just Intervals

Every candidate's internal monologue before the max() bug clicks
12. Merge Intervals (LC 56)
Sort intervals by start time. Walk through and merge each interval into the last one in your result if they overlap. Overlap condition: current.start <= last.end.
The max() call in the merge step is not optional. When one interval completely contains the next, you must take max(last.end, current.end), not just current.end. This is the bug that gets candidates. The code looks right. It is not.
def merge(intervals): intervals.sort(key=lambda x: x[0]) merged = [intervals[0]] for start, end in intervals[1:]: if start <= merged[-1][1]: merged[-1][1] = max(merged[-1][1], end) else: merged.append([start, end]) return merged
13. Meeting Rooms II (LC 253)
Given intervals representing meeting times, find the minimum rooms needed. Sort by start time, maintain a min-heap of end times. If the earliest-ending meeting finishes before the next starts, reuse the room. Otherwise, allocate one more.
This problem is really about concurrent resource allocation. Server thread pools, database connection limits, API rate limiting. Stripe and Airbnb use scheduling variants frequently. The heap is not an incidental detail. It is the whole insight.
Know Your Pointers. Know Your Heaps.
14. Linked List Cycle (LC 141)
Slow moves one step, fast moves two. If they meet, there is a cycle.
Foundational. It establishes the fast-slow pointer pattern that shows up in Floyd's cycle detection, middle-finding, and duplicate detection in bounded-range arrays. Compare pointers by identity, not value. That bug is more common than it has any right to be.
15. Kth Largest Element in an Array (LC 215)
The heap approach is almost always what the interviewer wants in a 45-minute round. Keep a min-heap of size K. Push each element, pop when the heap exceeds K. The root is the Kth largest.
import heapq def find_kth_largest(nums, k): heap = [] for n in nums: heapq.heappush(heap, n) if len(heap) > k: heapq.heappop(heap) return heap[0]
Appears regularly at Amazon, Uber, and Airbnb, typically framed as "top K users by activity" or "most popular N items." The heap keeps you from sorting the whole array. That is the point.
Don't Just Grind. Transfer.
Do not solve all 15 in one weekend. That is the LeetCode grinding mistake everyone makes. You will finish the weekend with 15 problems solved and zero patterns internalized.
Work through them by pattern. Do the hash map group, then ask yourself what all three have in common. Then stacks. Then trees. The pattern transfers across problems. That transfer is the actual skill.
For each problem: solve without hints, identify the exact line that was wrong or slow, write it down. That is your mistake log. Pre-interview, review the mistake log, not the full solutions.
Set a 25-minute timer. Not making progress at 15 minutes is the signal. On SpaceComplexity, you can run timed voice interviews that mirror full-stack rounds at real companies, including follow-up questions on complexity and design tradeoffs, where most candidates lose points after getting the algorithm right.
Further Reading
- LeetCode Top Interview 150 - the canonical problem set, heavily overlaps with this list
- GeeksforGeeks: Top 100 DSA Interview Questions - topic-organized reference
- Airbnb Interview Questions on LeetCode - company-tagged problems for one of the heaviest full-stack interviewers
- interviewing.io: Hash Tables Interview Questions - data-backed breakdowns of hash map problems at senior levels
- Wikipedia: Hash table - formal treatment of collision resolution and the math behind O(1) average case