Pattern #22

Subsets / Power Set

Important interview questions, thinking patterns, 3 generation techniques (Backtracking, Iterative, Bitmask), and rules for solving power set problems in Go.

Must Solve

12 core questions — solve these first.

  1. 1.Subsets
    medium
  2. 2.Subsets II
    medium
  3. 3.Combination Sum
    medium
  4. 4.Combination Sum II
    medium
  5. 5.Combinations
    medium
  6. 6.Letter Case Permutation
    medium
  7. 7.Generate Parentheses
    medium
  8. 8.Partition to K Equal Sum Subsets
    medium
  9. 9.Matchsticks to Square
    medium
  10. 10.Maximum Length of a Concatenated String with Unique Characters
    medium
  11. 11.Beautiful Arrangement
    medium
  12. 12.Letter Tile Possibilities
    medium

Also Important

8 more questions worth practicing.

  1. 13.Combination Sum III
    medium
  2. 14.Palindrome Partitioning
    medium
  3. 15.Restore IP Addresses
    medium
  4. 16.Split a String Into the Max Number of Unique Substrings
    medium
  5. 17.Count Number of Maximum Bitwise-OR Subsets
    medium
  6. 18.Find Minimum Time to Finish All Jobs
    hard
  7. 19.Fair Distribution of Cookies
    medium
  8. 20.Partition Equal Subset Sum
    medium

How to Think

  1. Need every possible subset?Take / Skip ($2^N$ possibilities)
  2. Each element can be chosen or ignored?Subsets
  3. Need all combinations of elements?Backtracking
  4. Input has duplicates?Sort + skip same-level duplicates
  5. N is small and every combination matters?$2^N$ power set

Go Subsets Backtracking Template

Standard Subsets Backtracking in Go

func subsets(nums []int) [][]int {
    results := [][]int{}
    path := []int{}

    var dfs func(start int)
    dfs = func(start int) {
        // Save current path at EVERY node (since every subset is valid!)
        copyPath := append([]int(nil), path...)
        results = append(results, copyPath)

        for i := start; i < len(nums); i++ {
            path = append(path, nums[i])
            dfs(i + 1) // Move start index forward to prevent reverse duplicates [2,1]
            path = path[:len(path)-1] // Undo
        }
    }

    dfs(0)
    return results
}

👉 Total Time: O(N × 2^N) | Space: O(N) (Recursion depth = N)

3 Ways to Generate Subsets

1. Backtracking
Save current -> Choose next -> Recurse -> Undo

Most flexible for constraints, pruning, and custom rules.

2. Iterative
Start [[]] -> For num: Duplicate existing + append num

Doubles subset result size on every new element.

3. Bitmask
0 to (2^N)-1 -> bit 1 = Take, bit 0 = Skip

Ideal for small N (N <= 20) with fast bitwise operations.

Subsets II — Skipping Duplicates

When the input contains duplicate values (e.g. [1, 2, 2]), sort first and skip duplicate choices at the same recursion level:

sort.Ints(nums)

for i := start; i < len(nums); i++ {
    // Skip duplicate elements competing at the SAME recursion level!
    if i > start && nums[i] == nums[i-1] {
        continue
    }

    path = append(path, nums[i])
    dfs(i + 1)
    path = path[:len(path)-1]
}
Visual Memory Rule
N elements  →  2^N subsets (Every element asks: TAKE or SKIP?)
Start Index →  Prevents duplicate orderings like [1,2] and [2,1]
Duplicates  →  Sort first + skip same-level duplicates (i > start && nums[i] == nums[i-1])

💡 Golden Rule: "Every element asks one question: 'Do I take it, or do I skip it?'"

Common Interview Mistakes

1. Forgetting Empty Set []

The empty set [] is always a valid subset of the power set!

2. Confusing Subset with Subarray

Subsets can pick elements from anywhere ([1, 3] from [1, 2, 3]), whereas Subarrays MUST be contiguous!

3. Generating Duplicate Orders

Generating both [1, 2] and [2, 1] for subsets is wrong. Use start index to keep combinations forward-moving!

4. Not Copying Path in Go

Saving path without copy causes later backtracking pops to mutate saved subset results!

Interview Rules

  1. 1. Every possible subset? → Take / Skip Backtracking
  2. 2. N elements2^N total subsets
  3. 3. Empty set [] is included in the power set
  4. 4. Order does not matter ([1,2] is identical to [2,1])
  5. 5. Use start index to avoid order duplicates
  6. 6. Duplicate input? → Sort first + skip same-level duplicates
  7. 7. Every current path is a valid answer → Save during traversal
  8. 8. Overall ComplexityO(N × 2^N) time, O(N) space

Small Rules

  1. Rule 1: Power set size is strictly 2^N.
  2. Rule 2: Backtracking recursion depth is O(N).
  3. Rule 3: Copying each subset of average size N/2 makes total work O(N × 2^N).
  4. Rule 4: Subsets do not care about order; Permutations DO care about order.
  5. Rule 5: Bitmask approach uses integers 0 to (2^N - 1) with bit 1 = Take, bit 0 = Skip.

Production Thinking

Product Feature Combinations4 optional features (Dark Mode, Push, Analytics, Offline) = 2^4 = 16 config subsets

API Permission TestingTest all combinations of Read/Write/Delete/Admin role flags

Feature Flag TestingTest 2^N feature flag enabled/disabled configurations

E-Commerce Search Filter SetsReason about active combinations of Price/Rating/Brand filters

Production WarningExponential explosion: N=20 is ~1 Million, N=30 is ~1 Billion subsets! Never generate power set for large N.

Remember This

Each element           → Take / Skip
n elements             → 2^n subsets
Subset                 → order doesn't matter
Empty set              → included
Backtracking           → save + choose + explore + undo
Duplicates             → sort + skip same level
Bitmask                → 0 skip, 1 take
Large n                → exponential explosion

💡 Golden Rule: "Every element asks one question: 'Do I take it, or do I skip it?'"