This problem extends the standard Permutations problem (LeetCode #46), with one added complication: the input can contain duplicate values. If we generate all permutations of [1, 1, 2] without any special handling, we get six results, but [1, 1, 2] appears twice (once when we pick the first 1 first, and once when we pick the second 1 first). Since both 1s are identical, those two results are the same permutation.
The challenge is not generating permutations. It is generating them without duplicates. We need a strategy that either avoids creating duplicates in the first place or filters them out afterward. The first option does less work.
One way to avoid duplicates: sort the array first so equal values sit next to each other. During backtracking, when choosing which element to place at the current position, we can skip a value if an identical copy was already tried at this position in an earlier branch.
1 <= nums.length <= 8 → The number of permutations is at most 8! = 40,320, so even generating all permutations and deduplicating afterward runs fast. Backtracking is the standard technique.-10 <= nums[i] <= 10 → Only 21 distinct values are possible, so with up to 8 elements, duplicates are common. The solution must handle them correctly.Ignore the duplicates entirely. Generate all n! permutations using standard backtracking, collect them into a set, and let the set discard the repeats.
A set discards equal entries automatically, so any permutation generated more than once is stored only once. The cost is wasted generation. For an input like [1, 1, 1, 1, 1, 1, 1, 1], there is only 1 unique permutation, but this generates all 8! = 40,320 of them and discards 40,319.
Input:
We generate all 3! = 6 permutations: [1a,1b,2], [1a,2,1b], [1b,1a,2], [1b,2,1a], [2,1a,1b], [2,1b,1a]. After deduplication, only 3 unique permutations remain:
This approach generates every permutation, including the duplicates, then discards the extras. The next approach skips duplicate branches before generating them.
Prevent duplicates from being generated instead of removing them afterward. Sort the array so equal values are adjacent, then during backtracking, skip an element if it has the same value as the previous element and the previous element is not used in the current partial permutation.
This forces a fixed ordering among equal elements. When multiple copies of a value exist, they must be placed in the order they appear in the sorted array. Labeling two equal 1s as 1a and 1b, the rule is: never place 1b before 1a.
The pruning condition nums[i] == nums[i-1] && !used[i-1] allows a copy to be placed only after the identical copy directly before it has been placed. So among a run of equal values, they always enter the permutation left to right. Each distinct permutation therefore corresponds to exactly one ordering of the equal copies, so it is generated once and only once.
used to track which elements are in the current partial permutation.i > 0 and nums[i] == nums[i-1] and used[i-1] is false (the pruning rule).used array takes O(n). Output is not counted in auxiliary space.The sorting approach needs an upfront sort and a pruning condition that is easy to get wrong. The next approach removes both by branching on values rather than indices.
Instead of tracking individual array indices, count the frequency of each distinct number. During backtracking, iterate over the distinct numbers and place one of each available value at the current position.
This avoids duplicates because the algorithm never distinguishes between individual copies of the same number. With three 1s, placing a 1 means decrementing the count of 1, not selecting a specific copy. There is no sort, no used array, and the skip condition becomes a single check: branch on a value only if its remaining count is greater than zero.
At each position the loop runs once per distinct value, so two branches at the same position never place the same value. A permutation is determined by the sequence of values chosen at each position, and that sequence is built one distinct choice at a time. Decrementing the count on the way down and restoring it on the way back keeps the available counts exact, so every valid arrangement is produced exactly once.