|
76 | 76 |
|
77 | 77 | --- |
78 | 78 |
|
79 | | -## 🧭 Quick Access Index |
80 | | -- [SubstringSlidingWindow](#substring-sliding-window) |
81 | | -- [TwoPointersTraversal](#two-pointers-traversal) |
82 | | -- [TwoPointerPartition](#two-pointer-partition) |
83 | | -- [FastSlowPointers](#fast-slow-pointers) |
84 | | -- [MergeSortedSequences](#merge-sorted-sequences) |
85 | | -- [KWayMerge](#k-way-merge) |
86 | | -- [HeapTopK](#heap-top-k) |
87 | | -- [LinkedListInPlaceReversal](#linked-list-in-place-reversal) |
88 | | -- [BacktrackingExploration](#backtracking-exploration) |
89 | | -- [GridBFSMultiSource](#grid-bfs-multi-source) |
90 | | -
|
91 | | ---- |
92 | | -
|
93 | 79 | ## 🧠 API Kernels (the “engines”) |
94 | 80 | ### SubstringSlidingWindow — *1D window state machine* |
95 | 81 | - ==Core invariant==: window \`[L,R]\` stays valid by **expand right** + **contract left** |
96 | | -- Complexity: typically $O(n)$ time, $O(n)$ space in worst case due to frequency map size |
| 82 | +- Complexity: typically $O(n)$ time, $O(\\Sigma)$ space (alphabet / distinct keys) |
97 | 83 |
|
| 84 | +<!-- markmap: fold --> |
98 | 85 | #### Pattern cheat sheet (from docs) |
99 | 86 | | Problem | Invariant | State | Window Size | Goal | |
100 | 87 | |---------|-----------|-------|-------------|------| |
101 | 88 | | [LeetCode 3 - Longest Substring Without Repeating Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0003_longest_substring_without_repeating_characters.py) | All unique | last index map | Variable | Max | |
102 | 89 | | [LeetCode 340 - Longest Substring with At Most K Distinct Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0340_longest_substring_with_at_most_k_distinct.py) | ≤K distinct | freq map | Variable | Max | |
103 | | -| [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) | window contains all characters of \`t\` with at least the required frequency | need/have | Variable | Min | |
| 90 | +| [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) | covers \`t\` | need/have | Variable | Min | |
104 | 91 | | [LeetCode 567 - Permutation in String](https://github.com/lufftw/neetcode/blob/main/solutions/0567_permutation_in_string.py) | exact freq match | freq + matches | Fixed | Exists | |
105 | 92 | | [LeetCode 438 - Find All Anagrams in a String](https://github.com/lufftw/neetcode/blob/main/solutions/0438_find_all_anagrams_in_a_string.py) | exact freq match | freq + matches | Fixed | All | |
106 | 93 | | [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py) | sum ≥ target | integer sum | Variable | Min | |
|
124 | 111 | - [ ] [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py) |
125 | 112 | - Typical requirement: positives → monotone contraction works |
126 | 113 |
|
127 | | -#### Real-world Application |
128 | | -- **Example**: Network packet analysis where you need to find the longest sequence of packets without repetition. |
129 | | -
|
130 | | -#### Problem-Solving Strategy |
131 | | -1. Identify the invariant condition for the window. |
132 | | -2. Use a frequency map to manage state. |
133 | | -3. Expand and contract the window to maintain the invariant. |
134 | | -
|
135 | | -#### See Also |
136 | | -- TwoPointersTraversal for similar problems involving sequence traversal. |
137 | | -
|
138 | 114 | --- |
139 | 115 |
|
140 | 116 | ### TwoPointersTraversal — *pointer choreography on sequences* |
|
144 | 120 | #### Pattern comparison (from docs) |
145 | 121 | | Pattern | Pointer Init | Movement | Termination | Time | Space | Key Use Case | |
146 | 122 | |---------|--------------|----------|-------------|------|-------|--------------| |
147 | | -| Opposite | \`0, n-1\` | toward center | \`L>=R\` | $O(n)$ | $O(1)$ | sorted pairs / palindrome / optimize | |
| 123 | +| Opposite | \`0, n-1\` | toward center | \`L>=R\` | $O(n)$ | $O(1)$ | sorted pairs / palindrome / maximize | |
148 | 124 | | Same-direction | \`write, read\` | forward | \`read==n\` | $O(n)$ | $O(1)$ | in-place modify | |
149 | 125 | | Fast–Slow | \`slow, fast\` | 1× / 2× | meet or null | $O(n)$ | $O(1)$ | cycle / midpoint | |
150 | 126 | | Dedup enum | \`i\` + \`L,R\` | nested | done | $O(n^2)$ | $O(1)$ | 3Sum/4Sum | |
|
174 | 150 | - 🎯 Problems |
175 | 151 | - [ ] [LeetCode 283 - Move Zeroes](https://github.com/lufftw/neetcode/blob/main/solutions/0283_move_zeroes.py) |
176 | 152 |
|
177 | | -#### When to Use Opposite vs. Same-Direction |
178 | | -- **Opposite Pointers**: Best for problems where elements are compared or combined from both ends (e.g., finding pairs). |
179 | | -- **Same-Direction Pointers**: Suitable for in-place modifications or when a single pass is needed. |
180 | | -
|
181 | | -#### Complexity Note |
182 | | -- Understand the difference between average-case and worst-case complexities, especially for inputs that may lead to different performance characteristics. |
183 | | -
|
184 | | -#### See Also |
185 | | -- Sliding Window techniques for problems involving dynamic window management. |
186 | | -
|
187 | | ---- |
188 | | -
|
189 | | -### TwoPointerPartition — *in-place partitioning “mini quicksort”* |
190 | | -- ==Core invariant==: elements are rearranged such that all elements satisfying the partition property precede those that do not |
191 | | -
|
192 | | -#### Patterns |
193 | | -- **dutch_flag_partition** |
194 | | - - 🎯 Problems |
195 | | - - [ ] [LeetCode 75 - Sort Colors](https://github.com/lufftw/neetcode/blob/main/solutions/0075_sort_colors.py) |
196 | | -- **two_way_partition** |
197 | | - - 🎯 Problems |
198 | | - - [ ] [LeetCode 905 - Sort Array By Parity](https://github.com/lufftw/neetcode/blob/main/solutions/0905_sort_array_by_parity.py) |
199 | | - - [ ] [LeetCode 922 - Sort Array By Parity II](https://github.com/lufftw/neetcode/blob/main/solutions/0922_sort_array_by_parity_ii.py) |
200 | | -- **quickselect_partition** *(selection via partition)* |
201 | | - - 🎯 Problems |
202 | | - - [ ] [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py) |
203 | | -
|
204 | | -#### Real-world Application |
205 | | -- **Example**: Efficiently organizing data such as segregating even and odd numbers in a dataset. |
206 | | -
|
207 | | -#### Problem-Solving Strategy |
208 | | -1. Choose a pivot or condition for partitioning. |
209 | | -2. Rearrange elements around the pivot to satisfy the partition property. |
210 | | -
|
211 | | -#### See Also |
212 | | -- FastSlowPointers for more advanced pointer manipulations. |
213 | | -
|
214 | 153 | --- |
215 | 154 |
|
216 | 155 | ### FastSlowPointers — *Floyd + midpoints + implicit sequences* |
|
225 | 164 | - **fast_slow_implicit_cycle** |
226 | 165 | - [ ] [LeetCode 202 - Happy Number](https://github.com/lufftw/neetcode/blob/main/solutions/0202_happy_number.py) |
227 | 166 |
|
228 | | -#### Real-world Application |
229 | | -- **Example**: Detecting cycles in network routing or data processing pipelines. |
230 | | -
|
231 | | -#### Problem-Solving Strategy |
232 | | -1. Use two pointers with different speeds. |
233 | | -2. Detect cycle presence and locate cycle start if needed. |
| 167 | +--- |
234 | 168 |
|
235 | | -#### See Also |
236 | | -- TwoPointerPartition for simpler partitioning tasks. |
| 169 | +### TwoPointerPartition — *in-place partitioning “mini quicksort”* |
| 170 | +- ==Core invariant==: regions are partitioned by property |
| 171 | +- Patterns |
| 172 | + - **dutch_flag_partition** |
| 173 | + - [ ] [LeetCode 75 - Sort Colors](https://github.com/lufftw/neetcode/blob/main/solutions/0075_sort_colors.py) |
| 174 | + - **two_way_partition** |
| 175 | + - [ ] [LeetCode 905 - Sort Array By Parity](https://github.com/lufftw/neetcode/blob/main/solutions/0905_sort_array_by_parity.py) |
| 176 | + - [ ] [LeetCode 922 - Sort Array By Parity II](https://github.com/lufftw/neetcode/blob/main/solutions/0922_sort_array_by_parity_ii.py) |
| 177 | + - **quickselect_partition** *(selection via partition)* |
| 178 | + - [ ] [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py) |
237 | 179 |
|
238 | 180 | --- |
239 | 181 |
|
240 | 182 | ### MergeSortedSequences — *merge two sorted sequences* |
241 | | -- ==Core invariant==: at each step, the smallest unmerged element is added to the output, maintaining sorted order |
| 183 | +- ==Core invariant==: output prefix is fully sorted |
242 | 184 | - Patterns |
243 | 185 | - **merge_two_sorted_lists** |
244 | 186 | - [ ] [LeetCode 21 - Merge Two Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0021_merge_two_sorted_lists.py) |
|
247 | 189 | - **merge_sorted_from_ends** |
248 | 190 | - [ ] [LeetCode 977 - Squares of a Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0977_squares_of_a_sorted_array.py) |
249 | 191 |
|
250 | | -#### Real-world Application |
251 | | -- **Example**: Merging sorted data streams or logs in real-time analytics systems. |
252 | | -
|
253 | | -#### Problem-Solving Strategy |
254 | | -1. Compare elements from the start of each sequence. |
255 | | -2. Append the smallest to the result and advance the pointer. |
256 | | -
|
257 | | -#### See Also |
258 | | -- KWayMerge for merging multiple sequences. |
259 | | -
|
260 | 192 | --- |
261 | 193 |
|
262 | 194 | ### KWayMerge — *merge K sorted sequences* |
|
267 | 199 | - [ ] [LeetCode 23 - Merge k Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0023_merge_k_sorted_lists.py) |
268 | 200 | - Related “hybrid thinking”: [LeetCode 4 - Median of Two Sorted Arrays](https://github.com/lufftw/neetcode/blob/main/solutions/0004_median_of_two_sorted_arrays.py) |
269 | 201 |
|
270 | | -#### Real-world Application |
271 | | -- **Example**: Combining multiple sorted data feeds into a single sorted output. |
272 | | -
|
273 | | -#### Problem-Solving Strategy |
274 | | -1. Use a min-heap to efficiently track the smallest elements. |
275 | | -2. Continuously extract and insert elements to maintain order. |
276 | | -
|
277 | | -#### See Also |
278 | | -- MergeSortedSequences for simpler two-sequence merging. |
279 | | -
|
280 | 202 | --- |
281 | 203 |
|
282 | 204 | ### HeapTopK — *keep best K under streaming updates* |
283 | 205 | - Patterns |
284 | 206 | - **heap_kth_element** |
285 | 207 | - [ ] [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py) |
286 | 208 |
|
287 | | -#### Real-world Application |
288 | | -- **Example**: Real-time leaderboard updates where only the top scores are maintained. |
289 | | -
|
290 | | -#### Problem-Solving Strategy |
291 | | -1. Use a min-heap to track the top K elements. |
292 | | -2. Insert new elements and remove the smallest when exceeding K. |
293 | | -
|
294 | | -#### See Also |
295 | | -- KWayMerge for merging top elements from multiple lists. |
296 | | -
|
297 | 209 | --- |
298 | 210 |
|
299 | 211 | ### LinkedListInPlaceReversal — *pointer surgery* |
|
303 | 215 | - Also core linked list arithmetic |
304 | 216 | - [ ] [LeetCode 2 - Add Two Numbers](https://github.com/lufftw/neetcode/blob/main/solutions/0002_add_two_numbers.py) |
305 | 217 |
|
306 | | -#### Edge Cases |
307 | | -- Handle empty lists or lists with fewer nodes than the reversal group size. |
308 | | -
|
309 | | -#### Real-world Application |
310 | | -- **Example**: Reversing segments of data in network packets for reordering. |
311 | | -
|
312 | | -#### Problem-Solving Strategy |
313 | | -1. Identify groups of nodes to reverse. |
314 | | -2. Use pointers to reverse nodes in place. |
315 | | -
|
316 | | -#### See Also |
317 | | -- FastSlowPointers for cycle detection in linked lists. |
318 | | -
|
319 | 218 | --- |
320 | 219 |
|
321 | 220 | ### BacktrackingExploration — *search tree with pruning* |
322 | 221 | - Pattern |
323 | 222 | - **backtracking_n_queens** |
324 | 223 | - [ ] [LeetCode 51 - N-Queens](https://github.com/lufftw/neetcode/blob/main/solutions/0051_n_queens.py) |
325 | 224 |
|
326 | | -#### Pruning Efficiency |
327 | | -- Pruning reduces the search space and improves efficiency by eliminating impossible paths early. |
328 | | -
|
329 | | -#### Real-world Application |
330 | | -- **Example**: Solving constraint satisfaction problems like Sudoku or N-Queens. |
331 | | -
|
332 | | -#### Problem-Solving Strategy |
333 | | -1. Explore all potential configurations. |
334 | | -2. Use pruning to eliminate invalid paths early. |
335 | | -
|
336 | | -#### See Also |
337 | | -- GridBFSMultiSource for exploring grid-based problems. |
338 | | -
|
339 | 225 | --- |
340 | 226 |
|
341 | 227 | ### GridBFSMultiSource — *wavefront propagation on grids* |
|
344 | 230 | - [ ] [LeetCode 994 - Rotting Oranges](https://github.com/lufftw/neetcode/blob/main/solutions/0994_rotting_oranges.py) |
345 | 231 | - Implementation invariant: queue holds frontier of current “minute/level” |
346 | 232 |
|
347 | | -#### Real-world Application |
348 | | -- **Example**: Simulating the spread of information or disease in a network. |
349 | | -
|
350 | | -#### Problem-Solving Strategy |
351 | | -1. Initialize the queue with all sources. |
352 | | -2. Propagate the wavefront level by level. |
| 233 | +--- |
353 | 234 |
|
354 | | -#### See Also |
355 | | -- BacktrackingExploration for exhaustive search techniques. |
| 235 | +## 🧭 Roadmap slices (what to do next) |
| 236 | +### Sliding Window Mastery 📚 |
| 237 | +- [ ] [LeetCode 3 - Longest Substring Without Repeating Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0003_longest_substring_without_repeating_characters.py) |
| 238 | +- [ ] [LeetCode 340 - Longest Substring with At Most K Distinct Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0340_longest_substring_with_at_most_k_distinct.py) |
| 239 | +- [ ] [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py) |
| 240 | +- [ ] [LeetCode 567 - Permutation in String](https://github.com/lufftw/neetcode/blob/main/solutions/0567_permutation_in_string.py) |
| 241 | +- [ ] [LeetCode 438 - Find All Anagrams in a String](https://github.com/lufftw/neetcode/blob/main/solutions/0438_find_all_anagrams_in_a_string.py) |
| 242 | +- [ ] [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) 🔥 |
| 243 | +
|
| 244 | +### Two Pointers Mastery ⚡ |
| 245 | +- Opposite pointers |
| 246 | + - [ ] [LeetCode 11 - Container With Most Water](https://github.com/lufftw/neetcode/blob/main/solutions/0011_container_with_most_water.py) |
| 247 | + - [ ] [LeetCode 125 - Valid Palindrome](https://github.com/lufftw/neetcode/blob/main/solutions/0125_valid_palindrome.py) |
| 248 | + - [ ] [LeetCode 680 - Valid Palindrome II](https://github.com/lufftw/neetcode/blob/main/solutions/0680_valid_palindrome_ii.py) |
| 249 | +- Writer pointers (in-place) |
| 250 | + - [ ] [LeetCode 26 - Remove Duplicates from Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0026_remove_duplicates_from_sorted_array.py) |
| 251 | + - [ ] [LeetCode 27 - Remove Element](https://github.com/lufftw/neetcode/blob/main/solutions/0027_remove_element.py) |
| 252 | + - [ ] [LeetCode 283 - Move Zeroes](https://github.com/lufftw/neetcode/blob/main/solutions/0283_move_zeroes.py) |
| 253 | + - [ ] [LeetCode 80 - Remove Duplicates from Sorted Array II](https://github.com/lufftw/neetcode/blob/main/solutions/0080_remove_duplicates_from_sorted_array_ii.py) |
| 254 | +- Fast–slow |
| 255 | + - [ ] [LeetCode 141 - Linked List Cycle](https://github.com/lufftw/neetcode/blob/main/solutions/0141_linked_list_cycle.py) |
| 256 | + - [ ] [LeetCode 142 - Linked List Cycle II](https://github.com/lufftw/neetcode/blob/main/solutions/0142_linked_list_cycle_ii.py) |
| 257 | + - [ ] [LeetCode 876 - Middle of the Linked List](https://github.com/lufftw/neetcode/blob/main/solutions/0876_middle_of_the_linked_list.py) |
| 258 | + - [ ] [LeetCode 202 - Happy Number](https://github.com/lufftw/neetcode/blob/main/solutions/0202_happy_number.py) |
356 | 259 |
|
357 | 260 | --- |
358 | 261 |
|
|
375 | 278 | L = 0 |
376 | 279 | ans = 0 |
377 | 280 | for R, x in enumerate(seq): |
378 | | - add(state, x) # Add current element to the state |
379 | | - while invalid(state): # While the state is invalid |
380 | | - remove(state, seq[L]) # Remove the leftmost element from the state |
381 | | - L += 1 # Move the left pointer right |
382 | | - ans = max(ans, R - L + 1) # Update the answer with the maximum window size |
| 281 | + add(state, x) |
| 282 | + while invalid(state): |
| 283 | + remove(state, seq[L]); L += 1 |
| 284 | + ans = max(ans, R - L + 1) |
383 | 285 | return ans |
384 | 286 |
|
385 | 287 | # Two pointers (opposite) |
386 | 288 | def opposite(arr): |
387 | 289 | L, R = 0, len(arr) - 1 |
388 | 290 | while L < R: |
389 | | - if should_move_left(arr, L, R): # Determine if left pointer should move |
| 291 | + if should_move_left(arr, L, R): |
390 | 292 | L += 1 |
391 | 293 | else: |
392 | | - R -= 1 # Otherwise, move the right pointer |
| 294 | + R -= 1 |
393 | 295 | \`\`\` |
394 | 296 |
|
395 | 297 | ---`; |
|
0 commit comments