- Interview Questions
- /
- Problems
- /
- Subsets II
Subsets II
List every distinct subset of an array that may contain repeated values. Backtracking over a sorted array, skipping equal siblings so no subset appears twice. Solve it below in Python or JavaScript, then read the walkthrough.
Problem
Given an integer array nums that may contain duplicates, return every distinct subset of it (its power set without repeats). Two subsets count as the same if they contain the same values with the same multiplicities, regardless of which positions they came from.
The empty subset is always included. You may return the subsets in any order, and the values inside each subset in any order too.
Example 1
- Input
- nums = [3, 1, 3]
- Output
- [[], [1], [1, 3], [1, 3, 3], [3], [3, 3]]
Picking the first 3 or the second 3 gives the same subset [3], so it is listed once. The same goes for [1, 3].
Example 2
- Input
- nums = [5, 5, 5]
- Output
- [[], [5], [5, 5], [5, 5, 5]]
With one repeated value, the only choice is how many copies to take.
Example 3
- Input
- nums = [-1, 0]
- Output
- [[], [-1], [-1, 0], [0]]
Constraints
- 1 ≤ nums.length ≤ 10
- -10 ≤ nums[i] ≤ 10
Practice
Runs 11 tests in your browser. Python loads on the first run (about 6 MB, then cached). Press ⌘/Ctrl + Enter to run.
Get asked Subsets II in a real interview?
Interview Solver gives you a working solution live, during your actual coding interview. Invisible to screensharing.
How to solve Subsets II
Pattern: Backtracking with duplicate skipping
Without duplicates, subsets come from a simple backtracking tree: at each level you choose the next index to add, always moving forward so each combination is built once.
Duplicates break that because two equal values at different positions lead to identical branches. The fix is to sort first, so equal values sit next to each other, then apply one rule: at a given level of the tree, only the first copy of a value may start a branch. If nums[i] == nums[i-1] and i isn't the first option at this level, skip it, because the branch starting at i-1 already produced everything the branch at i would.
You can still take several copies of a value; they just have to be taken by going deeper (copy 1, then copy 2 at the next level), never as sibling choices.
Approach 1: Generate all 2ⁿ subsets, de-duplicate
Build every subset by bitmask or plain backtracking, sort each one, and store it in a set of tuples (or strings) to drop repeats. Simple, but it still produces all 2ⁿ subsets, including the duplicates you throw away.
Time O(2ⁿ · n log n) · Space O(2ⁿ · n)
Approach 2: Count each value, choose how many copies
Count occurrences of each distinct value, then for each value choose to take 0, 1, …, count copies. The number of results is the product of (count + 1), with no duplicates ever generated. Correct and efficient; slightly more bookkeeping than the sorted version.
Time O(n · 2ⁿ) · Space O(n)
Approach 3: Sort and backtrack, skipping equal siblings
- Sort
nums. backtrack(start): record a copy of the current path as a subset. Then for eachifromstartto the end:- If
i > startandnums[i] == nums[i-1], skip it. - Otherwise append
nums[i], callbacktrack(i + 1), and pop it.
- If
- Call
backtrack(0)and return the collected subsets.
The i > start condition is what still allows [3, 3]: the second 3 is skipped as a sibling of the first, but allowed as its child.
Time O(n · 2ⁿ) · Space O(n) besides the output
| Approach | Time | Space |
|---|---|---|
| Generate all 2ⁿ subsets, de-duplicate | O(2ⁿ · n log n) | O(2ⁿ · n) |
| Count each value, choose how many copies | O(n · 2ⁿ) | O(n) |
| Sort and backtrack, skipping equal siblings | O(n · 2ⁿ) | O(n) besides the output |
Solution code
Try the practice editor first. Both solutions pass every test above.
Subsets II solution in Python
def subsets_with_dup(nums: list[int]) -> list[list[int]]:
nums = sorted(nums)
result = []
path = []
def backtrack(start: int) -> None:
result.append(path[:])
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]:
continue # same value already tried at this level
path.append(nums[i])
backtrack(i + 1)
path.pop()
backtrack(0)
return resultSubsets II solution in JavaScript
function subsetsWithDup(nums) {
const sorted = [...nums].sort((a, b) => a - b);
const result = [];
const path = [];
const backtrack = (start) => {
result.push([...path]);
for (let i = start; i < sorted.length; i++) {
if (i > start && sorted[i] === sorted[i - 1]) continue; // same value already tried at this level
path.push(sorted[i]);
backtrack(i + 1);
path.pop();
}
};
backtrack(0);
return result;
}Common mistakes
- Skipping duplicates without sorting first, so equal values aren't adjacent and the check misses them.
- Writing the skip condition as `i > 0` instead of `i > start`, which also blocks taking a second copy and loses subsets like [5, 5].
- Appending the path list itself instead of a copy, so every stored subset ends up as the same (empty) list after backtracking.
- Forgetting the empty subset.
What interviewers look for
Start from the version without duplicates and say what goes wrong: equal values at different positions generate the same branch twice. Then introduce sorting and the sibling-skip rule as the fix. Interviewers want to hear why i > start and not i > 0; trace [5, 5] to show the difference.
The same skip rule shows up in Combination Sum II and Permutations II, so pointing that out signals you recognize the family.
Follow-up questions
How many subsets can there be?
If the distinct values have counts c₁, c₂, …, the answer is the product of (cᵢ + 1). With no duplicates that is 2ⁿ; with all values equal it is n + 1.
Can you build the result iteratively instead of recursively?
Yes. Sort, then for each value extend existing subsets. For a new value, extend all of them. For a repeated value, only extend the subsets that were added in the previous step, since extending older ones would recreate subsets you already have.
What if you only want subsets of exactly size k?
Use the same backtracking but only record the path when its length is k, and stop recursing once it reaches k. You can also prune when fewer than k - len(path) elements remain.
Companies that ask Subsets II
Subsets II is tagged by 117 companies in our interview dataset. The score shows how often it comes up at each company.
- Thermo Fisher Scientific100%
- Oscar Health100%
- Infor100%
- Genesys100%
- Integrated Dna Technologies100%
- Rocket Mortgage96%
- Farfetch95%
- Carvana94%
- Red Hat93%
- General Atomics91%
- Kyndryl91%
- Unanet90%
- 10x Genomics90%
- Mips Technologies87%
- Asurion87%
- Epic87%
- Murex85%
- Bear Robotics84%
- Edmunds84%
- Jacobs83%
- Exl83%
- Vinted82%
- Leidos81%
- Slack80%
and 93 more.
Practice next
Get live help in the real interview
Working solutions in real time during your actual interview. Invisible to screensharing.
Start Free TrialNo credit card required