NeetCode 150 — Full Roadmap in C++¶
“Do not solve NeetCode 150 in shuffle mode. Do it in pattern mode. The order teaches you.”
This is the definitive 12-week march through NeetCode 150 in C++. Every category gets: the pattern in three sentences, the canonical C++ template, three to five must-solve problems with links, a time budget, and a suggested order.
Official list, still maintained by Navi (Neetcode) as of 2026: https://neetcode.io/practice/practice/neetcode150 and https://neetcode.io/roadmap
How to use this file¶
Do the categories in order. They build on each other. Arrays teaches loops, Two Pointers teaches invariants, Sliding Window teaches state maintenance, and so on. Do not skip ahead.
First pass: solve in Python, port to C++. For every new pattern (i.e., the first two or three problems of a category), sketch in Python first, then translate. This separates inventing the solution from typing it.
Second pass: C++ only, timed. Once you are three problems into a category, drop Python. Time yourself. Medium = 25 minutes. Easy = 12. Hard = 45.
After each problem, write the pattern label + complexity in a one-line comment at the top of the file. This becomes your NeetCode-150 repo (Project P2.1).
Category 1 — Arrays & Hashing (9 problems, W9)¶
Pattern in 3 sentences. Traverse the array once, maintain a hash-map of “what have I seen and where.” Constant-time lookup on hash converts nested-loop O(n²) brute-force into linear O(n). This is the most common trick in the entire list; internalize it first.
Canonical template:
std::unordered_map<int, int> seen;
for (int i = 0; i < (int)nums.size(); ++i) {
int need = target - nums[i];
if (auto it = seen.find(need); it != seen.end()) {
return {it->second, i};
}
seen[nums[i]] = i;
}
Must-solve (in order):
217. Contains Duplicate — warm-up
1. Two Sum — the archetype
49. Group Anagrams —
unordered_map<string, vector<string>>347. Top K Frequent Elements — bucket sort or heap
238. Product of Array Except Self — the prefix/suffix trick
128. Longest Consecutive Sequence — careful about O(n)
Time budget: W9. ~6 hours total.
Category 2 — Two Pointers (5 problems, W10)¶
Pattern in 3 sentences. Two indices walk the array with an invariant maintained between them. Usually one starts left, one right, and they converge; sometimes both start left and one races ahead. Reduces two-loop O(n²) scans to O(n) when the array has monotonic structure (usually sorted).
Canonical template:
int l = 0, r = nums.size() - 1;
while (l < r) {
int sum = nums[l] + nums[r];
if (sum == target) return {l, r};
if (sum < target) ++l;
else --r;
}
Must-solve:
15. 3Sum — the study classic; watch dedup logic
42. Trapping Rain Water — Hard; do it twice
Time budget: 4 hours.
Category 3 — Sliding Window (6 problems, W10)¶
Pattern in 3 sentences. Maintain a window [l, r) and a summary statistic (sum, count, hash-map). Grow r; when the invariant breaks, shrink l until it holds. Turns O(n·k) window-scans into amortized O(n).
Canonical template:
int l = 0, best = 0;
std::unordered_map<char, int> count;
for (int r = 0; r < (int)s.size(); ++r) {
count[s[r]]++;
while (/* invariant broken */) {
count[s[l]]--;
if (count[s[l]] == 0) count.erase(s[l]);
++l;
}
best = std::max(best, r - l + 1);
}
Must-solve:
76. Minimum Window Substring — Hard; the sliding-window boss level
239. Sliding Window Maximum — introduces monotonic deque
Time budget: 6 hours.
Category 4 — Stack (7 problems, W11)¶
Pattern in 3 sentences. Use a LIFO structure to defer decisions until later context arrives. Monotonic stacks (kept sorted while pushing) solve “next greater / next smaller” families in O(n). Parenthesis/bracket problems and expression evaluators are all stack problems in disguise.
Canonical template (monotonic stack for next greater):
std::vector<int> ans(nums.size(), -1);
std::stack<int> st; // indices, values strictly decreasing
for (int i = 0; i < (int)nums.size(); ++i) {
while (!st.empty() && nums[st.top()] < nums[i]) {
ans[st.top()] = nums[i];
st.pop();
}
st.push(i);
}
Must-solve:
22. Generate Parentheses — borderline backtracking
739. Daily Temperatures — canonical monotonic stack
84. Largest Rectangle in Histogram — Hard; do it twice
Time budget: 6 hours.
Category 5 — Binary Search (7 problems, W11)¶
Pattern in 3 sentences. Whenever the search space is monotonic in some predicate, halve it each step. The trick is recognizing the predicate: “is this a valid answer?” for binary-search-on-answer problems (BSoA). Learn to write the loop invariant (l < r, l ≤ r, half-open, etc.) and stick with one style.
Canonical template (half-open, no off-by-one):
int l = 0, r = n; // search in [l, r)
while (l < r) {
int m = l + (r - l) / 2; // avoid overflow
if (predicate(m)) r = m;
else l = m + 1;
}
// l is the smallest index where predicate holds, or n if none
Must-solve:
704. Binary Search — the primitive
875. Koko Eating Bananas — first BSoA
33. Search in Rotated Sorted Array — the classic
4. Median of Two Sorted Arrays — Hard; famously nasty
Time budget: 6 hours.
Category 6 — Linked List (11 problems, W12)¶
Pattern in 3 sentences. Two-pointer techniques (slow/fast for cycle and midpoint), reversal in place, and merge patterns cover 90% of linked-list problems. Draw the pointers on paper. Always — always — use a dummy head node to simplify edge cases at the start.
Canonical template (in-place reversal):
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev; // new head
Must-solve:
141. Linked List Cycle — Floyd’s tortoise-and-hare
146. LRU Cache — Medium but sneaky; use
list+unordered_map23. Merge k Sorted Lists — heap-based; Hard
Time budget: 8 hours.
Category 7 — Trees (11 problems, W12–W13)¶
Pattern in 3 sentences. Trees are recursion made physical. Master DFS in three orders (pre/in/post) and BFS by level. BST problems reduce to “in-order gives sorted”; general-tree problems reduce to “post-order lets me combine child answers.”
Canonical template (post-order aggregation):
int solve(TreeNode* node) {
if (!node) return 0;
int l = solve(node->left);
int r = solve(node->right);
// combine l and r with node->val to produce this subtree's answer
return /* ... */;
}
Must-solve:
543. Diameter — post-order aggregation
102. Level Order — BFS with queue
98. Validate BST — pass down min/max bounds
124. Binary Tree Max Path Sum — Hard; the archetype of “return one thing, track another globally”
Time budget: 10 hours.
Category 8 — Tries (3 problems, W13)¶
Pattern in 3 sentences. A tree of prefix nodes, one child per possible character. Insertion/lookup/prefix-search all O(L) in the length of the key. See file 03 for the full implementation with delete support.
Must-solve:
211. Design Add and Search Words — wildcard DFS on trie
212. Word Search II — Hard; trie + backtracking on grid
Time budget: 5 hours.
Category 9 — Heap / Priority Queue (7 problems, W13)¶
Pattern in 3 sentences. When you need the smallest (or largest) K, or a stream median, or repeatedly the current min/max of a changing set, reach for a heap. std::priority_queue is the tool; know the custom-comparator syntax cold (see file 01). For two-heap median tricks, keep one max-heap of the lower half and one min-heap of the upper half.
Must-solve:
215. Kth Largest Element — heap or quickselect
295. Find Median from Data Stream — Hard; the two-heap trick
Time budget: 6 hours.
Category 10 — Backtracking (9 problems, W14)¶
Pattern in 3 sentences. Depth-first exploration of a decision tree with explicit undo. The skeleton is always the same: try a choice, recurse, undo. The art is in pruning — spotting when a partial solution cannot possibly extend to a valid one.
Canonical template:
void backtrack(std::vector<int>& path, std::vector<std::vector<int>>& out, /*state*/) {
if (/* base case */) {
out.push_back(path);
return;
}
for (auto choice : choices(/*state*/)) {
if (!feasible(choice)) continue;
path.push_back(choice);
backtrack(path, out, /* updated state */);
path.pop_back(); // the undo
}
}
Must-solve:
79. Word Search — grid backtracking
51. N-Queens — Hard
Time budget: 8 hours.
Category 11 — Graphs (13 problems, W14–W15)¶
Pattern in 3 sentences. Every graph problem starts with a representation choice: adjacency list (vector<vector<int>>) is the default, adjacency matrix only for dense small graphs. BFS solves unweighted shortest path; DFS solves connectivity, cycle detection, and ordering. Grid problems are graph problems with implicit edges to the four (or eight) neighbors.
Canonical templates: See file 05 for BFS, DFS iterative and recursive, and grid neighbor patterns.
Must-solve:
200. Number of Islands — grid DFS/BFS
417. Pacific Atlantic Water Flow — multi-source BFS
207. Course Schedule — cycle detection / topo
210. Course Schedule II — Kahn’s algorithm
994. Rotting Oranges — multi-source BFS
<phone_number_or_numberic_id_or_random_id_12>. Redundant Connection — first union-find problem
Time budget: 10 hours.
Category 12 — Advanced Graphs (6 problems, W15)¶
Pattern in 3 sentences. Weighted shortest paths (Dijkstra, Bellman-Ford, Floyd-Warshall) and MST (Kruskal, Prim). The overwhelming majority of study questions here are Dijkstra variants; know the priority_queue<pair<int,int>> form cold. See file 05 for the copy-paste template.
Must-solve:
743. Network Delay Time — straight Dijkstra
787. Cheapest Flights With K Stops — Bellman-Ford or Dijkstra with state
<phone_number_or_numberic_id_or_random_id_13>. Swim in Rising Water — Dijkstra variant
269. Alien Dictionary — Hard; topological + string parse
Time budget: 8 hours.
Category 13 — 1D Dynamic Programming (12 problems, W16)¶
Pattern in 3 sentences. Identify the state (what does dp[i] mean?) and the transition (how does dp[i] derive from earlier dp[j]s?). Write the recursion first with memoization, then convert to bottom-up tabulation. Space-optimize last, and only if asked.
Canonical template (memo → tab):
// Memoized:
std::vector<int> memo(n, -1);
std::function<int(int)> f = [&](int i) -> int {
if (i >= n) return 0;
if (memo[i] != -1) return memo[i];
return memo[i] = std::min(cost[i] + f(i+1), cost[i] + f(i+2));
};
// Tabulated:
std::vector<int> dp(n + 2, 0);
for (int i = n - 1; i >= 0; --i) {
dp[i] = cost[i] + std::min(dp[i+1], dp[i+2]);
}
Must-solve:
70. Climbing Stairs — the primitive
213. House Robber II — circular twist
300. LIS — O(n²) DP then O(n log n) patience sorting
322. Coin Change — unbounded knapsack
Time budget: 10 hours.
Category 14 — 2D Dynamic Programming (11 problems, W17)¶
Pattern in 3 sentences. State is a pair (usually two indices into two strings, or (row, col) on a grid). Transitions come from the small neighborhood of (i, j). This is where DP goes from “comfortable” to “the study partner’s favorite filter.”
Must-solve:
62. Unique Paths — the primitive
1143. Longest Common Subsequence — the archetype
72. Edit Distance — the study classic
312. Burst Balloons — Hard, interval DP
Time budget: 10 hours.
Category 15 — Greedy (8 problems, W17)¶
Pattern in 3 sentences. Make the locally optimal choice at each step, and prove (or trust the problem-setter) that it composes into the global optimum. Greedy is deceptive: half the “greedy” LeetCode problems are actually DP problems that happen to admit a greedy solution. Always be able to argue why your greedy works.
Must-solve:
53. Max Subarray (Kadane) — the primitive
Time budget: 6 hours.
Category 16 — Intervals (6 problems, W18)¶
Pattern in 3 sentences. Sort by start (occasionally by end), then sweep. Overlap check is a.end > b.start. Rooms/meeting problems reduce to “count concurrent events” via a sweep line or a min-heap of end times.
Canonical template (merge overlapping):
std::sort(intervals.begin(), intervals.end());
std::vector<std::vector<int>> out;
for (auto& iv : intervals) {
if (!out.empty() && out.back()[1] >= iv[0]) {
out.back()[1] = std::max(out.back()[1], iv[1]);
} else {
out.push_back(iv);
}
}
Must-solve:
252/253. Meeting Rooms II — min-heap of end times
Time budget: 5 hours.
Category 17 — Math & Geometry (8 problems, W18)¶
Pattern in 3 sentences. No unifying pattern; a grab-bag of matrix rotations, spiral traversals, modular arithmetic, and Pascal’s triangle. study-frequency is medium. Skip the rare ones, do the popular ones.
Must-solve:
48. Rotate Image — transpose + reverse
73. Set Matrix Zeroes — the O(1) space trick
50. Pow(x, n) — fast exponentiation; watch integer overflow on
n = INT_MIN
Time budget: 5 hours.
Category 18 — Bit Manipulation (7 problems, W18)¶
Pattern in 3 sentences. XOR pairs to zero (finds unique element in duplicates). n & (n-1) clears the lowest set bit. Learn to think of an integer as 32 flags.
Canonical tricks:
n & (n - 1); // clears lowest set bit
n & (-n); // isolates lowest set bit
__builtin_popcount(n); // count set bits (GCC/Clang)
std::popcount(n); // C++20 portable
std::countl_zero(n); // C++20, leading zeros
Must-solve:
136. Single Number — XOR trick
338. Counting Bits — DP + bit trick
Time budget: 4 hours.
Overall progress log template¶
Maintain this table in your NeetCode repo README as you go. Public accountability compounds.
Week |
Category |
# Solved |
# In Budget |
# Retries |
Notes |
|---|---|---|---|---|---|
W9 |
Arrays & Hashing |
9 / 9 |
7 / 9 |
2 |
128 needed a second attempt |
What most people get wrong¶
They do NeetCode in shuffle mode from LeetCode’s daily challenge feed. Then they wonder why their pattern recognition is weak six months later. The categorical order exists for a reason: your brain builds pattern-buckets, not problem-memories. Do the categories in order, do each pattern until you can state the pattern in one sentence and produce the template in ten seconds, then move on.
The second failure mode: they solve every problem once and never revisit. Retention decays. Set a weekly re-solve of 3 random previously-solved problems, timed. If you cannot re-solve in half the original time, the pattern has not stuck.