RECURSION & SEARCH / ALGORITHM BRIEF

Permutations

A permutation is an ordering of all elements.

IntermediatePhase 06 / Topic 3 of 6Mental modelComplexityEdge cases
01

Overview

A permutation is an ordering of all elements. n distinct elements have n! permutations. Generating them uses backtracking: at each position, try every element not used yet, recurse to fill the next position, then undo.

Two implementations are common: a used[] boolean array with a path, or in-place swapping where you swap each candidate into the current position. With duplicate values, sort and skip a value if an identical earlier value has not been used yet, so identical orderings are not repeated.

Seating guests at a table

For the first chair you have n choices, for the second n - 1 remaining guests, and so on. Trying every seating plan means filling chairs one by one and swapping guests back out to try alternatives.

02

When to use it

  • All orderings or arrangements of items.
  • n is small (n <= 8 to 10; 10! is about 3.6 million).
  • The next lexicographic arrangement (next permutation) is needed.
  • Permutations with constraints (beautiful arrangements, no adjacent equal letters).
03

Problem patterns it solves

All permutations

Recognize it when: every ordering of distinct items.

  • 46. Permutations
  • 784. Letter Case Permutation
Permutations with duplicates

Recognize it when: repeated values; output must be unique.

  • 47. Permutations II
  • 1079. Letter Tile Possibilities
Next / kth permutation

Recognize it when: compute one specific ordering without generating all.

  • 31. Next Permutation
  • 60. Permutation Sequence
  • 556. Next Greater Element III
Constrained arrangements

Recognize it when: orderings that satisfy position rules.

  • 526. Beautiful Arrangement
  • 996. Number of Squareful Arrays
  • 267. Palindrome Permutation II
04

Where it is used in real software

Route optimization

Brute-force traveling salesman solutions try permutations of stops; real systems use heuristics because n! grows too fast.

Testing

Testing every order of operations to catch order-dependent bugs, for small numbers of steps.

Cryptography and shuffling

Fisher-Yates shuffling produces uniformly random permutations for card games and randomized experiments.

05

Key terms

n!
Number of permutations of n distinct items.
used[]
Marks which elements are already in the current path.
Swap-based permutation
Place each candidate at position i by swapping, recurse on i + 1, swap back.
Lexicographic order
Dictionary order of sequences.
06

How it works, step by step

  1. 1
    Base case

    When the path length equals n, record a copy.

  2. 2
    Try each unused element

    Loop i from 0 to n - 1, skipping used[i].

  3. 3
    Skip duplicates

    After sorting: if nums[i] === nums[i - 1] and !used[i - 1], skip.

  4. 4
    Choose, recurse, undo

    used[i] = true; path.push; recurse; path.pop; used[i] = false.

07

Next permutation of [1, 3, 5, 4, 2]

Find the next larger ordering in lexicographic order, in place

Step 1 / 4
StepActionArray
1From the right, find first i with a[i] < a[i + 1]: i = 1 (3 < 5)[1, 3, 5, 4, 2]
2From the right, find first j with a[j] > a[i]: j = 3 (4 > 3)[1, 3, 5, 4, 2]
3Swap a[i] and a[j][1, 4, 5, 3, 2]
4Reverse the suffix after i[1, 4, 2, 3, 5]

NOWStep: 1 | Action: From the right, find first i with a[i] < a[i + 1]: i = 1 (3 < 5) | Array: [1, 3, 5, 4, 2]

The suffix after i was in decreasing order (its largest arrangement); swapping in the next larger value and reversing the suffix gives the smallest arrangement with the new prefix. O(n), no generation of all permutations.

08

Implementation

function permute(nums) {  const result = [], path = [];  const used = new Array(nums.length).fill(false);  function backtrack() {    if (path.length === nums.length) {      result.push([...path]);      return;    }    for (let i = 0; i < nums.length; i++) {      if (used[i]) continue;      used[i] = true;      path.push(nums[i]);      backtrack();      path.pop();      used[i] = false;    }  }  backtrack();  return result;} // 47. Permutations IIfunction permuteUnique(nums) {  nums.sort((a, b) => a - b);  const result = [], path = [];  const used = new Array(nums.length).fill(false);  function backtrack() {    if (path.length === nums.length) { result.push([...path]); return; }    for (let i = 0; i < nums.length; i++) {      if (used[i]) continue;      if (i > 0 && nums[i] === nums[i - 1] && !used[i - 1]) continue; // use copies in order      used[i] = true;      path.push(nums[i]);      backtrack();      path.pop();      used[i] = false;    }  }  backtrack();  return result;} // 31. Next Permutationfunction nextPermutation(a) {  let i = a.length - 2;  while (i >= 0 && a[i] >= a[i + 1]) i--;  if (i >= 0) {    let j = a.length - 1;    while (a[j] <= a[i]) j--;    [a[i], a[j]] = [a[j], a[i]];  }  for (let l = i + 1, r = a.length - 1; l < r; l++, r--) [a[l], a[r]] = [a[r], a[l]];}
09

Complexity and performance

Generate allO(n! x n)

n! results, O(n) to copy each.

Next permutationO(n)

In place, O(1) extra space.

Kth permutationO(n^2)

Factorial number system; list removals.

SpaceO(n)

Recursion and used array.

10

Trade-offs

used[] vs swapping

used[] keeps output in lexicographic order for sorted input and makes duplicate handling easy. Swapping uses less memory but does not keep order.

Generate vs compute directly

For next or kth permutation, direct formulas avoid generating n! results.

11

Variants and related techniques

Heap's algorithm

Generates each permutation from the previous by a single swap.

Fisher-Yates shuffle

Uniform random permutation in O(n): swap a[i] with a random j <= i from the end.

Counting permutations with DP

Bitmask DP over used elements when you only need a count.

12

Common mistakes

  • Wrong duplicate rule.

    Fix: Skip when nums[i] === nums[i - 1] and !used[i - 1]; this forces identical values to be used in index order.

  • Forgetting to reverse the suffix in next permutation.

    Fix: After the swap, the suffix is still descending and must be reversed.

  • Running full generation for large n.

    Fix: n = 12 is already about 479 million permutations; look for a formula or DP.

13

Interview questions

How do you avoid duplicate permutations?

Sort the array. Only use a duplicate value if its previous identical copy is already used in the current path. This fixes the relative order of identical values, removing repeated orderings.

Explain next permutation.

Find the rightmost position where the sequence increases, swap that element with the smallest larger element to its right, then reverse the suffix to make it as small as possible.

14

Practice problems

ProblemDifficultyWhat it trains
46. PermutationsMediumCore backtracking.
47. Permutations IIMediumDuplicate rule.
31. Next PermutationMediumIn-place algorithm.
526. Beautiful ArrangementMediumPruning by position.
60. Permutation SequenceHardFactorial number system.