← DSA Atlas
Dedicated problem page · #47

Permutations II

MediumBacktrackingPermutation backtracking with used-array and duplicate skipDFS building full-length arrangements, pruning equal-value siblings
Solve on LeetCode ↗
47
MediumBacktrackingDFS building full-length arrangements, pruning equal-value siblingsPermutation backtracking with used-array and duplicate skip

Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations in any order.

Open official problem prompt ↗
In plain English

Produce every distinct ordering of a multiset without listing the same ordering twice.

Picture it like this

Arranging labeled tiles in a row, except two tiles share the identical face; you agree to always place the leftmost unused identical tile first so mirror-image arrangements never get counted twice.

Example
Input
nums = [1,1,2]
Output
[[1,1,2],[1,2,1],[2,1,1]]
Why
These are the three distinct orderings of the multiset {1,1,2}; swapping the two identical 1s produces no new permutation.
Constraints
1 <= nums.length <= 8-10 <= nums[i] <= 10
Pattern lesson

See the pattern, then code

Permutation backtracking with used-array and duplicate skip
Recognition clue

You must list all orderings but the input has repeats, so a plain permutation generator would emit duplicates - sort and skip equal values whose earlier twin is unused at this level.

Backtracking

Generate every valid combination, permutation, partition, or configuration.. To avoid duplicates, fix a canonical order among equal values: an equal element may only be placed if its identical predecessor has already been placed in this branch, so equal items are consumed left to right.

New words, made simpleKnow these before the algorithm
used array
Boolean flags marking which positions are already placed in the current permutation.
Canonical duplicate order
The rule that an equal value may enter only after its identical predecessor, giving each permutation one representative.
Permutation
An arrangement using every element exactly once.
Approaches from first idea to best ideaCompare the trade-offs
ApproachHow it thinksCost
Permute then dedupe

Correct but explores and stores many duplicates unnecessarily.

Generate all n! orderings and drop repeats via a set of tuples.

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

Invariant

Among any set of equal values, the ones already in the path always occupy an earlier-in-sorted-order set of positions, so each distinct permutation is generated by exactly one branch.

Why this is correct

Reasoning

The skip condition (nums[i]==nums[i-1] and not used[i-1]) forbids starting an equal value while its identical predecessor is still available, forcing left-to-right consumption of equal items. That gives every distinct arrangement a single canonical build path, eliminating duplicates while still reaching all of them.

The algorithm in three movesSay these aloud before coding
1Sort nums so equal values are adjacent

sorted=[1,1,2], used=[F,F,F]

2Track a used[] flag per position and build path

place nums[0]=1 -> used=[T,F,F], path=[1]

3When path length equals n, record a copy

next level: nums[1] allowed since nums[0] is used

4At each step skip an unused element equal to its predecessor whose predecessor is also unused

5Mark used, recurse, then unmark to explore other positions

Visual trace

Follow the data, one decision at a time

Input snapshotHighlighted cells are involved in this example
10
11
22
1 · Read[1,1,2]
2 · Askprepare
3 · Update stateused=[F,F,F], path=[]
4 · Resultstart recursion
Key takeaway

Sorted multiset [1,1,2]; identical 1s are consumed left to right to avoid duplicate permutations.

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 2-5Sort and state

    Sorting adjacency plus per-position used flags underpin the duplicate rule.

  2. 2
    Lines 6-8Base case

    A full-length path is a complete permutation; append a copy.

  3. 3
    Lines 9-13Skip and guard

    Skip already-used positions and equal siblings whose predecessor is unused.

  4. 4
    Lines 14-19Choose and undo

    Mark used, append, recurse, then restore both to try this position elsewhere.

Make it stick

Edge cases, mistakes, and one self-check

E

Edge cases to test

  • All elements identical, e.g. [2,2,2] -> a single permutation
  • All distinct -> full n! permutations
  • Single element -> one permutation
!

Common beginner mistakes

  • Using 'and used[i-1]' instead of 'and not used[i-1]', which flips the rule and drops valid permutations
  • Forgetting to sort, so equal values are not adjacent and the skip check misfires
  • Reusing the same position by not checking used[i]
Check your understanding

Why does the skip require nums[i-1] to be NOT used?