feat(patterns): pattern taxonomy + is_optimal

This commit is contained in:
2025-09-08 16:03:14 +01:00
parent 5b768f6a21
commit 13bab63618
28 changed files with 1434 additions and 26 deletions

View File

@@ -0,0 +1,96 @@
name: Cyclic Sort
slug: cyclic-sort
difficulty_level: 2
pattern_type: algorithm
display_order: 21
description: >
Place each number at its "correct" index when dealing with arrays containing
numbers in the range [1, n] or [0, n-1].
when_to_use: |
- Array contains numbers from 1 to n (or 0 to n-1)
- Finding missing/duplicate numbers in such arrays
- Problems asking for O(1) space and O(n) time
- "First missing positive" type problems
metaphor: |
Imagine a row of n chairs numbered 1 to n, and n people each holding a
ticket with their seat number. Instead of searching for each person's seat,
you ask everyone to swap positions until they're in their ticketed seat.
After at most n swaps, everyone is seated correctly.
core_concept: |
For an array where values should map directly to indices (e.g., value 3
belongs at index 2 if 1-indexed), repeatedly swap each element to its
correct position until the array is "sorted."
Key insight: Each swap places at least one element correctly, so at most
n swaps are needed -> O(n) time with O(1) space.
code_template: |
def cyclic_sort(nums: list[int]) -> list[int]:
"""Sort array where values are in range [1, n]."""
i = 0
while i < len(nums):
# Correct index for value nums[i] (1-indexed value -> 0-indexed position)
correct_idx = nums[i] - 1
# If not in correct position and not a duplicate, swap
if nums[i] != nums[correct_idx]:
nums[i], nums[correct_idx] = nums[correct_idx], nums[i]
else:
i += 1
return nums
def find_missing(nums: list[int]) -> int:
"""Find missing number after cyclic sort."""
cyclic_sort(nums)
for i, num in enumerate(nums):
if num != i + 1:
return i + 1
return len(nums) + 1
recognition_signals:
- "array of length n with values 1 to n"
- "find the missing number"
- "find the duplicate"
- "first missing positive"
- "O(1) extra space"
- "in-place rearrangement"
common_mistakes:
- title: Infinite Loop on Duplicates
description: |
Swapping endlessly when current value equals value at target index
(both are duplicates).
fix: |
Check `nums[i] != nums[correct_idx]` before swapping, not just
`nums[i] != correct_idx + 1`.
- title: Wrong Index Calculation
description: |
Confusing 0-indexed vs 1-indexed. If values are 1 to n, correct
index is `value - 1`. If values are 0 to n-1, correct index equals value.
fix: |
Clearly define the mapping: `correct_idx = nums[i] - 1` for 1-indexed values.
variations:
- name: Find Missing Number
description: After cyclic sort, scan for index where value != index + 1
example: "missing-number"
- name: Find Duplicate
description: After cyclic sort, find where value != expected
example: "find-the-duplicate-number"
- name: First Missing Positive
description: Ignore negatives and values > n, then cyclic sort
example: "first-missing-positive"
- name: Find All Missing Numbers
description: Collect all indices where value != expected
example: "find-all-numbers-disappeared-in-an-array"
related_patterns:
- counting-sort
- fast-slow-pointers
prerequisite_patterns: []