← DSA Atlas
Dedicated problem page · #46

Permutations

MediumBacktrackingPermutation generationBacktracking with a used[] marker
Solve on LeetCode ↗
46
MediumBacktrackingBacktracking with a used[] markerPermutation generation

Permutations

Given an array nums of distinct integers, return all possible permutations. You can return the answer in any order.

Open official problem prompt ↗
In plain English

List every distinct ordering of the input elements, using each element exactly once per ordering.

Picture it like this

Seating 3 guests in 3 chairs: for the first chair you have 3 choices, then 2, then 1, tracing out all 6 seating arrangements.

Example
Input
nums = [1, 2, 3]
Output
[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
Why
There are 3! = 6 orderings of three distinct elements, and each appears exactly once.
Constraints
1 <= nums.length <= 6-10 <= nums[i] <= 10All the integers of nums are unique
Pattern lesson

See the pattern, then code

Permutation generation
Recognition clue

Asking for ALL orderings / arrangements (not combinations) of a tiny array is the permutation-backtracking signal; here order matters, so no start index is used.

Backtracking

Generate every valid combination, permutation, partition, or configuration.. A permutation uses every element exactly once, so unlike subsets we scan all indices each level and only skip those already placed. A used[] boolean array marks which elements are currently in the path.

New words, made simpleKnow these before the algorithm
Permutation
An ordered arrangement using every element once; order distinguishes permutations from combinations.
used[] array
Booleans tracking which elements are already placed in the current path so none is reused.
Depth = n
The base case: a complete permutation has been built once the path length matches the input length.
Approaches from first idea to best ideaCompare the trade-offs
ApproachHow it thinksCost
Insert-into-every-gap recursion

Correct but copies many intermediate lists, using more memory than needed.

Build permutations of the first k elements, then insert the next element into each possible gap.

Time O(n * n!)Space O(n * n!)
The rule we keep true

Invariant

At every call, path is a duplicate-free sequence of placed elements and used[i] is True exactly for the elements currently in path.

Why this is correct

Reasoning

Each level chooses one not-yet-used element, so after n levels every element appears exactly once, giving a valid permutation. Because every unused index is tried at every level, all n! orderings are reached; the paired mark/unmark keeps used[] consistent so no branch leaks state into another.

The algorithm in three movesSay these aloud before coding
1When the path length equals n, record a copy as a finished permutation

path=[1] used={0}

2Loop over every index; skip indices whose used flag is set

path=[1,2] used={0,1}

3Mark used, append, recurse, then unmark and pop to restore state

path=[1,2,3] -> record

Visual trace

Follow the data, one decision at a time

Input snapshotHighlighted cells are involved in this example
10
21
32
1 · Readpath=[]
2 · AskWhich first element?
3 · Update stateused=[F,F,F]
4 · ResultPick 1, used[0]=T
Key takeaway

Fixing 1 first, the subtree yields [1,2,3] and [1,3,2] before backtracking to fix 2.

Code walkthrough

Read the solution in small chunks

Python 3

Do not memorize the whole program. Connect each group of lines to one job in the algorithm.

  1. 1
    Lines 7-10Completion check

    When path has n elements the permutation is complete; store a copy and return.

  2. 2
    Lines 11-13Skip placed elements

    Iterate every index and skip any already in the path via the used flag.

  3. 3
    Lines 14-18Mark, recurse, restore

    Set used[i], push nums[i], recurse to the next depth, then pop and clear used[i] to try the next choice.

Make it stick

Edge cases, mistakes, and one self-check

E

Edge cases to test

  • Single element -> [[x]]
  • Two elements -> two permutations
  • Negative numbers are handled identically since values are only placed, never compared
!

Common beginner mistakes

  • Forgetting to reset used[i] = False after recursion, which blocks later branches
  • Appending path without copying so all results alias one list
  • Using a start index (that would generate combinations, not permutations)
Check your understanding

Why is there no start index here, unlike in the subsets and combination-sum solutions?