Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.
Example 1:
Input: nums = [1,1,2] Output: [[1,1,2], [1,2,1], [2,1,1]]
Example 2:
Input: nums = [1,2,3] Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Constraints:
1 <= nums.length <= 8-10 <= nums[i] <= 10Problem Overview: Given an array that may contain duplicate numbers, generate every unique permutation. The challenge is avoiding duplicate permutations that arise when the same value appears multiple times in different positions.
Approach 1: Backtracking with Used Array (O(n! * n) time, O(n) space)
This approach sorts the array first, then builds permutations using backtracking. A boolean used[] array tracks which indices are already part of the current permutation. During iteration, skip an element if it is already used or if it equals the previous element and the previous element was not used in this recursion level. That condition prevents generating duplicate orderings. Each recursive step appends a number, explores deeper, then backtracks by removing it. Sorting plus the duplicate-skip rule ensures every permutation is produced exactly once.
The algorithm explores a permutation tree of depth n. Constructing each permutation takes O(n), and there can be up to n! permutations, giving O(n! * n) time complexity. Auxiliary space is O(n) for recursion and the used array (excluding output). This is the most common solution in interviews because it demonstrates clean pruning logic and understanding of permutation generation.
Approach 2: Recursive Swap with Set (O(n! * n) time, O(n) space)
This method treats the array like a permutation-in-progress and swaps elements into the current position. At recursion depth i, iterate from i to the end and swap each candidate into index i. To avoid duplicates, maintain a Set for the current recursion level that records which values have already been placed at index i. If a value has been used in this position before, skip it. After the recursive call finishes, swap the elements back to restore the original order.
The swap approach avoids maintaining a separate path array and works directly on the array. It generates permutations in-place and prevents duplicate branches using the per-level set. Time complexity remains O(n! * n) because each permutation requires copying or constructing a length-n list, and the recursion tree can grow factorially. Space complexity is O(n) for recursion depth plus the temporary set used at each level.
Recommended for interviews: Backtracking with a sorted array and a used[] check is the standard answer. It clearly shows how duplicate pruning works and is easier to reason about under pressure. The swap-with-set method is also valid and demonstrates deeper understanding of permutation generation, but interviewers typically expect the sorted backtracking approach when solving permutation problems with duplicates.
This approach uses backtracking to generate permutations and a boolean array to track used elements in the current permutation combination. By sorting the array at the start, we can easily skip duplicates.
This Python solution uses recursion and backtracking to generate permutations. Sorting the nums list initially helps to efficiently skip duplicates by checking if the element is the same as the previous one and if the previous one has been used.
Java
JavaScript
C#
C
Time Complexity: O(n * n!) due to the generation of all permutations.
Space Complexity: O(n!) for storing the permutations and O(n) for the recursion stack.
This method carries out permutations by recursively swapping elements and employs a set to track unique permutations and avoid generating duplicate results. It does not require sorting initially but uses swaps directly to generate permutations.
Implementing permutations through swapping allows the program to manage the sequence in-place and recursively form permutations, collecting results in a set for uniqueness.
Java
JavaScript
C#
Time Complexity: O(n * n!)
Space Complexity: O(n * n!) because of the set used to store permutations.
| Approach | Complexity |
|---|---|
| Backtracking with Used Array | Time Complexity: O(n * n!) due to the generation of all permutations. |
| Recursive Swap with Set | Time Complexity: O(n * n!) |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Backtracking with Used Array | O(n! * n) | O(n) | Most common interview solution; clean duplicate pruning after sorting |
| Recursive Swap with Set | O(n! * n) | O(n) | When generating permutations in-place without a separate path array |
Permutations II - Backtracking - Leetcode 47 • NeetCode • 104,344 views views
Watch 9 more video solutions →Practice Permutations II with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor