Alkesh

LeetCode - Subsets

Problem statement

Given an integer array nums of unique elements, return all possible subsets (the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

Problem statement taken from: https://leetcode.com/problems/subsets

Example 1:

Input: nums = [1, 2, 3]
Output: [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

Example 2:

Input: nums = [0]
Output: [[], [0]]

Constraints:

- 1 <= nums.length <= 10
- -10 <= nums[i] <= 10
- All the numbers of nums are unique.

Explanation

Backtracking

The general strategy in backtracking is either to include the current element or exclude it. We follow similar approach here. When running the recursive call we either include the current element or we exclude it.

Let's check the algorithm.

// main function
- initialize subset vector: vector<int> subset
- initialize result vector: vector<vector<int>> result

- call subsetsUtil(nums, result, subset, 0)

- return result

// subsetsUtil function
- res.push_back(subset)

- loop for i = index; i < nums.size(); i++
  - subset.push_back(nums[i])

  - subsetsUtil(nums, result, subset, i + 1)

  - subset.pop_back()

- return

C++ solution

class Solution {
public:
    void subsetsUtil(vector<int>& nums, vector<vector<int>>& result, vector<int>& subset, int index) {
        result.push_back(subset);

        for(int i = index; i < nums.size(); i++){
            subset.push_back(nums[i]);

            subsetsUtil(nums, result, subset, i + 1);

            subset.pop_back();
        }

        return;
    }

public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<int> subset;
        vector<vector<int>> result;

        subsetsUtil(nums, result, subset, 0);

        return result;
    }
};

Golang solution

func subsets(nums []int) [][]int {
    result := make([][]int, 0)

    subsetsUtils(nums, &result, []int{}, 0)

    return result
}

func subsetsUtils(nums []int, result *[][]int, subset []int, index int) {
    *result = append(*result, append([]int{}, subset...))

    for i := index; i < len(nums); i++ {
		subset = append(subset, nums[i])

		subsetsUtils(nums, result, subset, i + 1)

		subset = subset[:len(subset)-1]
	}
}

Javascript solution

var subsets = function(nums) {
    function findSubset(array, subset) {
        result.push([...subset]);

        for(let i = 0; i < array.length; i++) {
            subset.push(array[i]);

            findSubset(array.slice(i + 1), subset);

            subset.pop();
        }
    }

    let result = [];
    findSubset(nums, []);
    return result;
};

Dry Run

Let's dry-run our algorithm to see how the solution works.

Input: nums = [1, 2, 3]

Step 1: vector<int> subset
        vector<vector<int>> result

Step 2: subsetsUtil(nums, res, subset, 0)

// in subsetsUtils function
Step 3: result.push_back(subset)
        result.push_back([])

        result = [[]]

        loop for i = index, i < nums.size()
        i = 0
        0 < 3
        true

        subset.push_back(nums[i])
        subset.push_back(nums[0])
        subset.push_back(1)

        subset = [1]

        subsetsUtil(nums, res, subset, i + 1)
        subsetsUtil([1, 2, 3], [[]], [1], 0 + 1)
        subsetsUtil([1, 2, 3], [[]], [1], 1)

Step 4: result.push_back(subset)
        result.push_back([1])

        result = [[], [1]]

        loop for i = index, i < nums.size()
        i = 1
        1 < 3
        true

        subset.push_back(nums[i])
        subset.push_back(nums[1])
        subset.push_back(2)

        subset = [1, 2]

        subsetsUtil(nums, res, subset, i + 1)
        subsetsUtil([1, 2, 3], [[], [1]], [1, 2], 1 + 1)
        subsetsUtil([1, 2, 3], [[], [1]], [1, 2], 2)

Step 5: result.push_back(subset)
        result.push_back([1, 2])

        result = [[], [1], [1, 2]]

        loop for i = index, i < nums.size()
        i = 2
        2 < 3
        true

        subset.push_back(nums[i])
        subset.push_back(nums[2])
        subset.push_back(3)

        subset = [1, 2, 3]

        subsetsUtil(nums, res, subset, i + 1)
        subsetsUtil([1, 2, 3], [[], [1], [1, 2]], [1, 2, 3], 2 + 1)
        subsetsUtil([1, 2, 3], [[], [1], [1, 2]], [1, 2, 3], 3)

Step 6: result.push_back(subset)
        result.push_back([1, 2, 3])

        result = [[], [1], [1, 2], [1, 2, 3]]

        loop for i = index, i < nums.size()
        i = 3
        3 < 3
        false

Step 7: Here we backtrack to last line of Step 5 where
        i = 2
        subset = [1, 2, 3]

        We execute the next line
        subset.pop()

        subset = [1, 2]

Step 8: We backtrack to last line of Step 4 where
        i = 1
        subset = [1, 2]

        We execute the next line
        subset.pop()

        subset = [1]

Step 9: For loop continues where we execute
        loop for i = index, i < nums.size()
        i = 2
        i < nums.size()
        2 < 3
        true

        subset.push_back(nums[i])
        subset.push_back(nums[2])
        subset.push_back(3)

        subset = [1, 3]

        subsetsUtil(nums, res, subset, i + 1)
        subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3]], [1, 3], 2 + 1)
        subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3]], [1, 3], 3)

Step 10: result.push_back(subset)
         result.push_back([1, 3])

         result = [[], [1], [1, 2], [1, 2, 3], [1, 3]]

         loop for i = index, i < nums.size()
         i = 3
         3 < 3
         false

Step 11: Here we backtrack to last line of Step 3 where
         i = 0
         subset = [1]

         We execute the next line
         subset.pop()

         subset = []

Step 12: For loop continues where we execute
         loop for i = index, i < nums.size()
         i = 1
         i < nums.size()
         1 < 3
         true

         subset.push_back(nums[i])
         subset.push_back(nums[1])
         subset.push_back(2)

         subset = [2]

         subsetsUtil(nums, res, subset, i + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3]], [2], 1 + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3]], [2], 2)

Step 13: result.push_back(subset)
         result.push_back([2])

         result = [[], [1], [1, 2], [1, 2, 3], [1, 3], [2]]

         loop for i = index, i < nums.size()
         i = 2
         2 < 3
         true

         subset.push_back(nums[i])
         subset.push_back(nums[2])
         subset.push_back(3)

         subset = [2, 3]

         subsetsUtil(nums, res, subset, i + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3], [2]], [2, 3], 2 + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3], [2]], [2, 3], 3)

Step 14: result.push_back(subset)
         result.push_back([2, 3])

         result = [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3]]

         loop for i = index, i < nums.size()
         i = 3
         3 < 3
         false

Step 15: Here we backtrack to last line of Step 13 where
         i = 2
         subset = [2, 3]

         We execute the next line
         subset.pop()

         subset = [2]

Step 16: Here we backtrack to last line of Step 12 where
         i = 1
         subset = [2]

         We execute the next line
         subset.pop()

         subset = []

Step 17: For loop continues where we execute
         loop for i = index, i < nums.size()
         i = 2
         i < nums.size()
         2 < 3
         true

         subset.push_back(nums[i])
         subset.push_back(nums[2])
         subset.push_back(3)

         subset = [3]

         subsetsUtil(nums, res, subset, i + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3]], [3], 2 + 1)
         subsetsUtil([1, 2, 3], [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3]], [3], 3)

Step 18: result.push_back(subset)
         result.push_back([3])

         result = [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

         loop for i = index, i < nums.size()
         i = 3
         3 < 3
         false

Step 19: We have no more stack entries left. We return to main function.

Step 20: return result

So the result we return is [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]].
Share this post!