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: []