78. Subsets - Detailed Explanation
Problem Statement
Description:
Given an array of distinct integers nums
, return all possible subsets (the power set).
A subset is a collection of elements from nums
(possibly none), and each subset must be unique.
Example 1:
- Input:
nums = [1, 2, 3]
- Output:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
- Explanation:
- The empty set
[]
is a subset. - All one-element subsets:
[1]
,[2]
,[3]
- All two-element subsets:
[1, 2]
,[1, 3]
,[2, 3]
- The full set:
[1, 2, 3]
- The empty set
Example 2:
- Input:
nums = [0]
- Output:
[[], [0]]
- Explanation:
- The empty set and the single-element set
[0]
are all possible subsets.
- The empty set and the single-element set
Constraints:
- The length of
nums
is between 1 and 10 (or more depending on variations). - All elements in
nums
are distinct. - The solution should generate 2ⁿ subsets (where n is the number of elements), so be mindful of exponential growth in output.
Hints
-
Hint 1:
Think of each element as having two options: either you include it in a subset or you do not. This binary decision for every element suggests that the total number of subsets will be 2ⁿ. -
Hint 2:
Consider using recursion (backtracking) where at each step you decide to include or exclude the current element, then move on to the next element. -
Hint 3:
You can also use iterative approaches or bit manipulation to generate all possible combinations.
Approach 1: Backtracking (Depth-First Search)
Idea
Use recursion to explore two choices at every index: include the current element or skip it. This way, you build a tree where each node represents a decision point, and the leaves of this tree represent one subset.
Steps
-
Start with an empty subset:
Begin with an empty list representing the current subset. -
Recursive Decision:
For each element in the array, decide:- Include the element in the current subset.
- Exclude the element and move to the next.
-
Base Case:
When you reach the end of the array, add the current subset to your list of subsets. -
Backtrack:
Remove the last element (if added) and try the next decision.
Visual Walkthrough
For nums = [1, 2, 3]
:
- Start with
[]
. - At index 0 (element 1):
- Include 1 →
[1]
- At index 1 (element 2):
- Include 2 →
[1, 2]
- At index 2 (element 3):
- Include 3 →
[1, 2, 3]
→ add to result. - Exclude 3 →
[1, 2]
→ add to result.
- Include 3 →
- At index 2 (element 3):
- Exclude 2 →
[1]
- At index 2 (element 3):
- Include 3 →
[1, 3]
→ add to result. - Exclude 3 →
[1]
→ add to result.
- Include 3 →
- At index 2 (element 3):
- Include 2 →
- At index 1 (element 2):
- Exclude 1 →
[]
- At index 1 (element 2):
- Include 2 →
[2]
- At index 2 (element 3):
- Include 3 →
[2, 3]
→ add to result. - Exclude 3 →
[2]
→ add to result.
- Include 3 →
- At index 2 (element 3):
- Exclude 2 →
[]
- At index 2 (element 3):
- Include 3 →
[3]
→ add to result. - Exclude 3 →
[]
→ add to result.
- Include 3 →
- At index 2 (element 3):
- Include 2 →
- At index 1 (element 2):
- Include 1 →
Approach 2: Iterative Method
Idea
Start with an empty subset and then for each element in nums
, add it to every existing subset in your results list to create new subsets.
Steps
-
Initialize Result:
Start withresult = [[]]
. -
Iterate Through
nums
:
For each number, iterate over the current subsets inresult
and add a new subset that includes the current number. -
Combine:
Append these new subsets back to the result.
Visual Walkthrough
For nums = [1, 2, 3]
:
- Start:
[[]]
- Process 1: Add
[1]
to each subset →[[], [1]]
- Process 2: For each subset in
[[], [1]]
:- Add 2 →
[2]
and[1, 2]
→ now result becomes[[], [1], [2], [1, 2]]
- Add 2 →
- Process 3: For each subset in
[[], [1], [2], [1, 2]]
:- Add 3 →
[3]
,[1, 3]
,[2, 3]
,[1, 2, 3]
→ final result becomes[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
.
- Add 3 →
Code Implementation
Python Code (Backtracking Approach)
Java Code (Backtracking Approach)
Complexity Analysis
-
Time Complexity:
- There are 2ⁿ possible subsets (where n is the number of elements in
nums
). - For each subset, creating a copy takes O(n) time in the worst case.
- Overall: O(n * 2ⁿ).
- There are 2ⁿ possible subsets (where n is the number of elements in
-
Space Complexity:
- The space required to store all the subsets is O(2ⁿ * n) in the worst case.
- Additionally, the recursion stack (in the backtracking approach) can go as deep as O(n).
Step-by-Step Walkthrough and Visual Example
Using nums = [1, 2, 3]
with the backtracking approach:
-
Start:
Current subset is[]
, add it to results. -
At index 0:
- Include 1 → current subset becomes
[1]
→ add[1]
to results. - Recurse starting at index 1.
- At index 1:
- Include 2 → current subset becomes
[1, 2]
→ add[1, 2]
. - Recurse starting at index 2.
- At index 2:
- Include 3 → current subset becomes
[1, 2, 3]
→ add[1, 2, 3]
. - Backtrack (remove 3) → current subset reverts to
[1, 2]
.
- Include 3 → current subset becomes
- Exclude 3 → backtrack to index 1 level.
- At index 2:
- Backtrack (remove 2) → current subset reverts to
[1]
. - At index 2:
- Include 3 → current subset becomes
[1, 3]
→ add[1, 3]
. - Backtrack (remove 3) → current subset reverts to
[1]
.
- Include 3 → current subset becomes
- Include 2 → current subset becomes
- At index 1:
- Backtrack (remove 1) → current subset becomes
[]
.
- Include 1 → current subset becomes
-
At index 1 (from empty subset):
- Include 2 → current subset becomes
[2]
→ add[2]
. - Recurse starting at index 2.
- At index 2:
- Include 3 → current subset becomes
[2, 3]
→ add[2, 3]
. - Backtrack (remove 3) → current subset reverts to
[2]
.
- Include 3 → current subset becomes
- At index 2:
- Backtrack (remove 2) → current subset becomes
[]
.
- Include 2 → current subset becomes
-
At index 2 (from empty subset):
- Include 3 → current subset becomes
[3]
→ add[3]
. - Backtrack → current subset becomes
[]
.
- Include 3 → current subset becomes
All subsets are now generated.
Common Mistakes and Edge Cases
Common Mistakes
-
Not Copying the Current Subset:
Remember to add a copy of the current subset to the result; otherwise, subsequent modifications will change previously added subsets. -
Incorrect Base Case:
Make sure to add the current subset to the result at each recursion level, not just when you reach the end. -
Duplicate Handling:
Although the problem states all elements are distinct, ensure your approach would handle duplicates gracefully if required (by sorting and skipping duplicate values).
Edge Cases
-
Empty Input Array:
For an emptynums
, the only subset is the empty set:[[]]
. -
Single Element:
Fornums = [a]
, the subsets are[[], [a]]
.
Variations
-
Subsets II:
A variation wherenums
may contain duplicates. In that case, you must ensure that no duplicate subsets are generated. -
Combination Sum / Combination Problems:
Problems that require generating combinations of elements that sum up to a target or satisfy certain conditions.
Related Problems for Further Practice
-
Permutations:
Generate all possible orderings of an array. -
Combination Sum:
Find all combinations that add up to a target value. -
Power Set:
Directly related to generating all subsets of a set.
GET YOUR FREE
Coding Questions Catalog
