Subsets Generation Using Bitmask in DSA C - Time & Space Complexity
We want to understand how the time needed to generate all subsets grows as the input size increases.
Specifically, how does the number of operations change when we use bitmasking to create subsets?
Analyze the time complexity of the following code snippet.
void generateSubsets(int arr[], int n) {
int total = 1 << n; // 2^n subsets
for (int mask = 0; mask < total; mask++) {
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
// include arr[i] in current subset
}
}
}
}
This code generates all subsets of an array by using bitmasking to decide which elements to include.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The inner loop checks each element for every subset mask.
- How many times: The outer loop runs 2^n times, and the inner loop runs n times for each outer loop.
As the input size n grows, the total subsets double each time, and for each subset, we check n elements.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * 2^10 = 10,240 |
| 20 | About 20 * 2^20 = 20,971,520 |
| 30 | About 30 * 2^30 = 32,212,254,720 |
Pattern observation: The operations grow very fast, doubling with each increase in n, multiplied by n.
Time Complexity: O(n * 2^n)
This means the time needed grows very fast as input size increases, because we generate all subsets and check each element.
[X] Wrong: "Generating subsets is just O(2^n) because there are 2^n subsets."
[OK] Correct: We also check each element for every subset, so the inner loop adds a factor of n, making it O(n * 2^n).
Understanding this complexity helps you explain why generating all subsets is expensive and shows your grasp of exponential growth in algorithms.
"What if we only printed subsets of a fixed size k instead of all sizes? How would the time complexity change?"
Practice
Solution
Step 1: Understand bitmask representation
Each bit in the bitmask represents whether an element is included (1) or excluded (0) in a subset.Step 2: Generate subsets using bitmask
By iterating from 0 to 2^n - 1, all combinations of included/excluded elements are covered, producing all subsets.Final Answer:
All possible subsets of the set -> Option AQuick Check:
Bitmask = All subsets [OK]
- Thinking bitmask generates only largest subsets
- Confusing bitmask with subsets of fixed size
- Assuming bitmask excludes empty subset
Solution
Step 1: Understand bitmask range
Bitmask must cover all numbers from 0 to 2^n - 1, which is (1 << n) in C.Step 2: Check loop conditions
Loop from 0 to less than (1 << n) correctly iterates all subsets.Final Answer:
for (int mask = 0; mask < (1 << n); mask++) -> Option BQuick Check:
Loop from 0 to 2^n-1 [OK]
- Using mask <= n instead of mask < 2^n
- Starting loop from 1 excludes empty subset
- Using mask < n only covers n subsets
int arr[] = {1, 2};
int n = 2;
for (int mask = 0; mask < (1 << n); mask++) {
printf("{");
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
printf("%d", arr[i]);
}
}
printf("}\n");
}Solution
Step 1: Understand bitmask iterations
mask goes from 0 to 3 (binary 00 to 11), representing subsets: empty, {1}, {2}, {1,2}.Step 2: Trace output formatting
Elements printed without spaces or commas, so subsets print as {}, {1}, {2}, {12}.Final Answer:
{} {1} {2} {12} -> Option CQuick Check:
Bitmask subsets printed without separators [OK]
- Assuming spaces or commas between elements
- Confusing bitmask order of elements
- Missing empty subset output
int arr[] = {1, 2, 3};
int n = 3;
for (int mask = 0; mask <= (1 << n); mask++) {
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
printf("%d ", arr[i]);
}
}
printf("\n");
}Solution
Step 1: Check loop range correctness
Loop runs from 0 to (1 << n) inclusive, which is 0 to 8 for n=3, but max mask should be 7 (0 to 7).Step 2: Identify off-by-one error
Using mask <= (1 << n) causes mask=8, which is out of valid subset range, causing incorrect behavior.Final Answer:
Loop condition should be mask < (1 << n), not <= -> Option AQuick Check:
Loop must run from 0 to 2^n - 1 [OK]
- Starting loop from 1 excludes empty subset
- Using <= causes out-of-range mask
- Misunderstanding bitwise AND usage
arr = {1, 2, 3, 4}, how many subsets generated by bitmask will have exactly two elements?Solution
Step 1: Calculate total subsets of size 2
Number of subsets with exactly 2 elements from 4 elements is combination 4 choose 2 = 6.Step 2: Understand bitmask filtering
Among all 2^4=16 subsets, exactly 6 have two bits set in their bitmask representing two elements included.Final Answer:
6 -> Option DQuick Check:
Combination(4,2) = 6 [OK]
- Counting total subsets instead of size 2
- Confusing subsets with permutations
- Miscounting bitmask bits set
Ready to prove it?
Pass the test and this pattern moves unknown
