Last Updated: April 1, 2026
We need to generate every possible subset of the given array. A subset is any selection of elements (including none or all) from the array, where order does not matter. For an array of n elements, there are exactly 2^n subsets.
What makes this problem interesting is not just finding one subset, but systematically enumerating all of them without missing any and without producing duplicates. Think of it this way: for each element, you have a binary choice, include it or exclude it. That's n binary choices, giving 2^n total outcomes.
The key observation is that this "include or exclude" framing maps directly to both a recursive backtracking approach and a bitmask-based approach. Each gives us a clean way to explore every possible combination of choices.
1 <= nums.length <= 10 → With n at most 10, there are at most 2^10 = 1024 subsets. Any exponential approach is fine.-10 <= nums[i] <= 10 → Small value range, but all elements are unique, so we don't need to worry about deduplication.The simplest way to think about generating all subsets is to build them up one element at a time. Start with just the empty set. Then for each element in the array, look at every subset you've generated so far, make a copy of it with the new element added, and include that copy in your collection.
Here's why this works. When you process the first element, you take the empty set [] and create [1], giving you [[], [1]]. When you process the second element, you take each of those and add 2: [] becomes [2] and [1] becomes [1,2]. Now you have [[], [1], [2], [1,2]]. Each step doubles the number of subsets, which is exactly what we want since n elements produce 2^n subsets.
a. Look at every subset currently in the result.
b. Create a new subset by appending the current number to each existing subset.
c. Add all these new subsets to the result.
This approach is simple and correct, but involves a lot of list copying at each step. The backtracking approach builds subsets incrementally and only copies when a complete subset is recorded, making it the standard interview pattern for subset generation.
Backtracking is the classic approach for this problem. It maps directly to the fundamental insight: for each element, you either include it or you don't. Picture a decision tree where at each level you decide about one element. Every node in this tree represents a valid subset, so we record it at every recursive call.
In practice, we iterate through the remaining elements starting from a given index. At each recursive call, we pick the next element to add, recurse, and then undo (backtrack) that choice. By always picking elements at index >= start, we ensure each subset is generated exactly once.
The backtracking approach works because it systematically explores every possible combination of include/exclude decisions. By always picking elements at index >= start, we never revisit earlier elements, which would create duplicates in different orders.
The "add to result at every call" trick is what makes this different from combinations or permutations: we don't wait for some base case to record a result. Every partial selection is itself a valid subset, from the empty set all the way up to the full array.
a. Add nums[i] to the current subset.
b. Recurse with start index = i + 1.
c. Remove nums[i] from the current subset (backtrack).
Both the iterative and backtracking approaches have the same time complexity. But there is a completely different way to think about subset generation using bit manipulation, where each subset maps directly to a binary number.
Here is an elegant observation: for an array of n elements, there are 2^n subsets and also 2^n binary numbers from 0 to 2^n - 1. Each binary number of length n can represent a subset. If bit j is 1, element j is included. If bit j is 0, element j is excluded.
So we can generate all subsets by iterating from 0 to 2^n - 1 and, for each number, checking which bits are set to determine which elements belong in that subset. No recursion, no backtracking, just a direct mapping from integers to subsets.
a. Create a new subset.
b. For each bit position j from 0 to n - 1: if bit j of mask is set, add nums[j] to the subset.
c. Add the subset to the result.