Patterns/Part I - Arrays & Pointers/Array Tricks

Pattern Reference

Array Tricks

"Cyclic rotation, reversal-based operations, in-place swaps, and the Dutch flag."

Loading...

Deep Dive Tutorial

Array in-place manipulation problems have a deceptive pattern: the O(n) extra space solution is obvious, but the O(1) space version requires a non-trivial trick. Learn the three canonical tricks — 3-reversal rotation, negation marking, and index encoding — and you'll be able to solve a whole class of problems that seem impossible at O(1) space.

The Three Canonical Tricks

Rotate array, mark visited, index encoding
// TRICK 1: ROTATE ARRAY k positions (right) using 3 reverses
function rotate(nums, k) {
    k = k % nums.length;
    const rev = (lo, hi) => { while(lo<hi) [nums[lo++],nums[hi--]]=[nums[hi],nums[lo-1]]; };
    rev(0, nums.length-1);  // reverse all
    rev(0, k-1);             // reverse first k
    rev(k, nums.length-1);   // reverse remaining
}
// Why it works: [1,2,3,4,5], k=2
// reverse all: [5,4,3,2,1]
// reverse 0..k-1: [4,5,3,2,1]
// reverse k..n-1: [4,5,1,2,3] ✓

// TRICK 2: MARK VISITED by negating (array values 1..n)
// Visit index i → nums[nums[i]-1] = -|nums[nums[i]-1]|
// Check if value v is visited: nums[v-1] < 0
function findDuplicates(nums) {
    const result = [];
    for (const n of nums) {
        const idx = Math.abs(n) - 1;
        if (nums[idx] < 0) result.push(Math.abs(n)); // visited twice = duplicate
        else nums[idx] = -nums[idx]; // mark visited
    }
    return result;
}

// TRICK 3: CYCLIC SORT (array with values 1..n)
// Place each number at index (value-1) by swapping
function cyclicSort(nums) {
    let i = 0;
    while (i < nums.length) {
        const j = nums[i] - 1; // correct index for nums[i]
        if (nums[i] !== nums[j]) [nums[i], nums[j]] = [nums[j], nums[i]]; // swap to correct pos
        else i++;                // already in place, move on
    }
}
// After cyclic sort: nums[i] = i+1 iff no duplicate/missing

Worked Problems

wrench
Array manipulation trick selector:
- "Rotate k positions in O(1) space" → 3 reverses
- "Mark visited without extra space (values 1..n)" → negate at index value-1
- "Place each value at correct index (1..n)" → cyclic sort
- "Find missing/duplicate in 1..n array" → cyclic sort, then scan for mismatch
- "Next permutation" → find rightmost dip, swap with just-larger, reverse suffix
- "Rearrange by condition" → two pointers with step 2 for alternating pattern