Generate All Subsets: Power Set with Backtracking

Sanjeev SharmaSanjeev Sharma
2 min read

Advertisement

Generate All Subsets

Algorithm: Include/Exclude

At each index, decide: include this element or skip it.

Python Implementation

def subsets(nums):
    result = []
    def bt(start, current):
        result.append(current[:])  # snapshot at every node
        for i in range(start, len(nums)):
            current.append(nums[i])
            bt(i + 1, current)
            current.pop()  # backtrack
    bt(0, [])
    return result

print(subsets([1, 2, 3]))
# [[], [1], [1,2], [1,2,3], [1,3], [2], [2,3], [3]]

# Subsets II (with duplicates): sort + skip same sibling
def subsetsWithDup(nums):
    nums.sort()
    result = []
    def bt(start, current):
        result.append(current[:])
        for i in range(start, len(nums)):
            if i > start and nums[i] == nums[i-1]:
                continue  # skip duplicate at same level
            current.append(nums[i])
            bt(i + 1, current)
            current.pop()
    bt(0, [])
    return result

# Bitmask approach
def subsets_bitmask(nums):
    n = len(nums)
    result = []
    for mask in range(1 << n):
        subset = [nums[i] for i in range(n) if mask >> i & 1]
        result.append(subset)
    return result

C++ Implementation

#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> subsets(vector<int>& nums) {
    vector<vector<int>> result;
    vector<int> current;
    function<void(int)> bt = [&](int start) {
        result.push_back(current);
        for (int i = start; i < (int)nums.size(); i++) {
            current.push_back(nums[i]);
            bt(i + 1);
            current.pop_back();
        }
    };
    bt(0);
    return result;
}

vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    vector<vector<int>> result;
    vector<int> current;
    function<void(int)> bt = [&](int start) {
        result.push_back(current);
        for (int i = start; i < (int)nums.size(); i++) {
            if (i > start && nums[i] == nums[i-1]) continue;
            current.push_back(nums[i]);
            bt(i + 1);
            current.pop_back();
        }
    };
    bt(0);
    return result;
}

Java Implementation

import java.util.*;

public class Subsets {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        backtrack(nums, 0, new ArrayList<>(), result);
        return result;
    }

    void backtrack(int[] nums, int start, List<Integer> current, List<List<Integer>> result) {
        result.add(new ArrayList<>(current));
        for (int i = start; i < nums.length; i++) {
            current.add(nums[i]);
            backtrack(nums, i + 1, current, result);
            current.remove(current.size() - 1);
        }
    }
}

JavaScript Implementation

function subsets(nums) {
    const result = [];
    function bt(start, current) {
        result.push([...current]);
        for (let i = start; i < nums.length; i++) {
            current.push(nums[i]);
            bt(i + 1, current);
            current.pop();
        }
    }
    bt(0, []);
    return result;
}

Complexity

  • Time: O(2^n * n) — 2^n subsets, each takes O(n) to copy
  • Space: O(n) recursion depth

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro