Generate All Subsets Powerset in DSA C++ - Time & Space Complexity
We want to understand how the time needed to generate all subsets of a set grows as the set size increases.
How does the number of subsets affect the work done by the algorithm?
Analyze the time complexity of the following code snippet.
void generateSubsets(vector<int>& nums, vector<int>& current, int index, vector<vector<int>>& result) {
if (index == nums.size()) {
result.push_back(current);
return;
}
// Include nums[index]
current.push_back(nums[index]);
generateSubsets(nums, current, index + 1, result);
// Exclude nums[index]
current.pop_back();
generateSubsets(nums, current, index + 1, result);
}
This code generates all subsets (the powerset) of the input list by choosing to include or exclude each element recursively.
- Primary operation: Recursive calls that branch twice at each element.
- How many times: For n elements, there are 2 choices (include/exclude) per element, leading to 2^n recursive calls.
Each new element doubles the number of subsets, so the work grows very fast.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 1,024 subsets generated |
| 20 | About 1,048,576 subsets generated |
| 30 | About 1,073,741,824 subsets generated |
Pattern observation: The number of operations doubles with each additional element, showing exponential growth.
Time Complexity: O(2^n * n)
This means the time grows exponentially with the number of elements, because we generate all subsets and each subset can take up to n steps to copy.
[X] Wrong: "Generating all subsets is just like looping once over the array, so it should be O(n)."
[OK] Correct: Each element doubles the number of subsets, so the total work grows exponentially, not linearly.
Understanding this exponential growth helps you explain why generating all subsets is costly and when it is practical to use.
"What if we only wanted subsets of a fixed size k? How would the time complexity change?"
Practice
{1, 2}?Solution
Step 1: Understand what subsets mean
Subsets include all combinations of elements, from empty to full set.Step 2: List all subsets of {1, 2}
They are {}, {1}, {2}, and {1, 2}.Final Answer:
All possible subsets including empty set: {}, {1}, {2}, {1, 2} -> Option BQuick Check:
Subsets = all combinations [OK]
- Thinking subsets only have full or single elements
- Ignoring the empty subset
- Confusing subsets with permutations
Solution
Step 1: Identify correct vector declaration
We need a vector of vectors of int to store subsets.Step 2: Check syntax correctness
std::vector subsets; uses correct syntax: std::vector subsets; initializes empty vector of vectors.Final Answer:
std::vector subsets; -> Option CQuick Check:
Correct vector of vectors syntax [OK]
- Using vector<int> instead of vector
- Incorrect template syntax like vector subsets<int>
- Trying to initialize with empty braces incorrectly
std::vector<int> nums = {1, 2};
std::vector subsets = {{}};
for (int num : nums) {
int n = subsets.size();
for (int i = 0; i < n; i++) {
std::vector<int> newSubset = subsets[i];
newSubset.push_back(num);
subsets.push_back(newSubset);
}
}
for (auto &subset : subsets) {
for (int x : subset) std::cout << x << " ";
std::cout << "| ";
}Solution
Step 1: Understand initial subsets and loop
Initially subsets = {{}}, empty subset only. For each num, we add new subsets by adding num to existing subsets.Step 2: Trace iterations
For num=1: subsets become {}, {1}. For num=2: subsets become {}, {1}, {2}, {1, 2}.Final Answer:
| | 1 | 2 | 1 2 | -> Option AQuick Check:
All subsets printed with spaces and separators [OK]
- Missing the empty subset in output
- Printing subsets in wrong order
- Confusing push_back inside loop
std::vector<int> nums = {1, 2};
std::vector subsets;
for (int num : nums) {
int n = subsets.size();
for (int i = 0; i < n; i++) {
std::vector<int> newSubset = subsets[i];
newSubset.push_back(num);
subsets.push_back(newSubset);
}
}Solution
Step 1: Check initialization of subsets
subsets is empty initially, so subsets.size() is 0, inner loop never runs.Step 2: Identify missing empty subset
We must start subsets with empty subset {{}} to build new subsets correctly.Final Answer:
subsets vector is not initialized with empty subset before loop -> Option AQuick Check:
Empty subset needed to start building subsets [OK]
- Not initializing subsets with empty subset
- Changing loop start index incorrectly
- Misplacing push_back calls
nums = {1, 2, 2}, which code modification ensures the generated subsets contain no duplicate subsets?Solution
Step 1: Understand duplicates in input
Input has duplicate 2's, so subsets like {2} can appear multiple times.Step 2: Use sorting and skip duplicates
Sorting nums helps detect duplicates; skip adding subsets with same element consecutively to avoid duplicates.Final Answer:
Sort nums first and skip adding duplicates during subset generation. -> Option DQuick Check:
Sorting + skipping duplicates avoids repeated subsets [OK]
- Assuming duplicates never occur
- Removing duplicates from input loses valid subsets
- Using set after generation is less efficient
Ready to prove it?
Pass the test and this pattern moves unknown
