Print all subsets of a given Set or Array
Given a set of positive integers, find all its subsets.
Examples:
Input: array = {1, 2, 3} Output: // this space denotes null element. 1 1 2 1 2 3 1 3 2 2 3 3 Explanation: These are all the subsets that can be formed using the array. Input: 1 2 Output: 1 2 1 2 Explanation: These are all the subsets that can be formed using the array.
The iterative solution is already discussed here: the iterative approach to find all subsets. This article aims to provide a backtracking approach.
Approach: The idea is simple, that if there are n number of elements inside an array, there are n number of choices for the first element in the array. Moving forward to the next recursion call, there will be n-1 number of choices (as we cannot insert the last element again now) for inserting the second element in the array.
Using the above idea forms a recursive solution to the problem.
Algorithm:
- Create a recursive function that takes the following parameters, input array, the current index, the output array, or current subset, if all the subsets need to be stored then a vector of the array is needed if the subsets need to be printed only then this space can be ignored.
- First, print the subset (output array) that has been sent to the function and then run a for loop starting from the ‘index’ to n-1 where n is the size of the input array. We use a loop to demonstrate that we have exactly n number of choices to choose from when adding the first element to our new array.
- Inside the loop, we call the function for the next index after inserting that particular index and then in the next call, we again have (n-1) choices to choose from and so it goes.
- Whenever a call is made for the last index of the array : in that function call, the loop is not run as the condition i<A.size() is not fulfilled and hence, we backtrack to the last recursion call and call the function for the next index after removing the element at that current index.
- We finally return when the initial loop ends and we have received all the subsets possible.
Implementation:
C++
// CPP program to find all subsets by backtracking. #include <bits/stdc++.h> using namespace std; // For our vector subset, at every step we have A.size()-i-1 // choices to include. A loop helps us to choose each element // and then move to the indices further present in the array. // At the end we backtrack to choose a different index. void subsetsUtil(vector< int >& A, vector<vector< int > >& res, vector< int >& subset, int index) { res.push_back(subset); // Loop to choose from different elements present // after the current index 'index' for ( int i = index; i < A.size(); i++) { // include the A[i] in subset. subset.push_back(A[i]); // move onto the next element. subsetsUtil(A, res, subset, i + 1); // exclude the A[i] from subset and triggers // backtracking. subset.pop_back(); } return ; } // below function returns the subsets of vector A. vector<vector< int > > subsets(vector< int >& A) { vector< int > subset; vector<vector< int > > res; // keeps track of current element in vector A // and the number of elements present in the array subset int index = 0; subsetsUtil(A, res, subset, index); return res; } // Driver Code. int main() { // find the subsets of below vector. vector< int > array = { 1, 2, 3 }; // res will store all subsets. // O(2 ^ (number of elements inside array)) // because total number of subsets possible // are O(2^N) vector<vector< int > > res = subsets(array); // Print result for ( int i = 0; i < res.size(); i++) { for ( int j = 0; j < res[i].size(); j++) cout << res[i][j] << " " ; cout << endl; } return 0; } |
Java
/*package whatever // do not write package name here */ import java.io.*; import java.util.*; class GFG { public static void findSubsets(List<List<Integer> > subset, ArrayList<Integer> nums, ArrayList<Integer> output, int index) { // Base Condition if (index == nums.size()) { subset.add(output); return ; } // Not Including Value which is at Index findSubsets(subset, nums, new ArrayList<>(output), index + 1 ); // Including Value which is at Index output.add(nums.get(index)); findSubsets(subset, nums, new ArrayList<>(output), index + 1 ); } public static void main(String[] args) { // Main List for storing all subsets List<List<Integer> > subset = new ArrayList<>(); // Input ArrayList ArrayList<Integer> input = new ArrayList<>(); input.add( 1 ); input.add( 2 ); input.add( 3 ); findSubsets(subset, input, new ArrayList<>(), 0 ); // Comparator is used so that all subset get // sorted in ascending order of values Collections.sort(subset, (o1, o2) -> { int n = Math.min(o1.size(), o2.size()); for ( int i = 0 ; i < n; i++) { if (o1.get(i) == o2.get(i)) { continue ; } else { // sort based on the unequal elements value return o1.get(i) - o2.get(i); } } // sort based on size return o1.size() - o2.size(); }); // Printing Subset for ( int i = 0 ; i < subset.size(); i++) { for ( int j = 0 ; j < subset.get(i).size(); j++) { System.out.print(subset.get(i).get(j) + " " ); } System.out.println(); } } } |
Python3
# Python3 program to find all subsets # by backtracking. # In the array A at every step we have two # choices for each element either we can # ignore the element or we can include the # element in our subset def subsetsUtil(A, subset, index): print ( * subset) for i in range (index, len (A)): # include the A[i] in subset. subset.append(A[i]) # move onto the next element. subsetsUtil(A, subset, i + 1 ) # exclude the A[i] from subset and # triggers backtracking. subset.pop( - 1 ) return # below function returns the subsets of vector A. def subsets(A): global res subset = [] # keeps track of current element in vector A index = 0 subsetsUtil(A, subset, index) # Driver Code # find the subsets of below vector. array = [ 1 , 2 , 3 ] # res will store all subsets. # O(2 ^ (number of elements inside array)) # because at every step we have two choices # either include or ignore. subsets(array) # This code is contributed by SHUBHAMSINGH8410 |
C#
/*package whatever // do not write package name here */ using System; using System.Collections.Generic; public class GFG { public static void findSubsets(List<List< int > > subset, List< int > nums, List< int > output, int index) { // Base Condition if (index == nums.Count) { subset.Add(output); return ; } // Not Including Value which is at Index findSubsets(subset, nums, new List< int >(output), index + 1); // Including Value which is at Index output.Add(nums[index]); findSubsets(subset, nums, new List< int >(output), index + 1); } public static void Main(String[] args) { // Main List for storing all subsets List<List< int > > subset = new List<List< int > >(); // Input List List< int > input = new List< int >(); input.Add(1); input.Add(2); input.Add(3); findSubsets(subset, input, new List< int >(), 0); // Comparator is used so that all subset get // sorted in ascending order of values subset.Sort((o1, o2) = > { int n = Math.Min(o1.Count, o2.Count); for ( int i = 0; i < n; i++) { if (o1[i] == o2[i]) { continue ; } else { return o1[i] - o2[i]; } } return 1; }); // Printing Subset for ( int i = 0; i < subset.Count; i++) { for ( int j = 0; j < subset[i].Count; j++) { Console.Write(subset[i][j] + " " ); } Console.WriteLine(); } } } // This code is contributed by shikhasingrajput |
Javascript
<script> /*package whatever //do not write package name here */ function findSubsets(subset, nums, output, index) { // Base Condition if (index == nums.length) { subset.push(output); return ; } // Not Including Value which is at Index findSubsets(subset, nums, [...output], index + 1); // Including Value which is at Index output.push(nums[index]); findSubsets(subset, nums, [...output], index + 1); } // Main List for storing all subsets let subset = []; // Input ArrayList let input = []; input.push(1); input.push(2); input.push(3); findSubsets(subset, input, [], 0); // Comparator is used so that all subset get // sorted in ascending order of values subset.sort((o1, o2) => { let n = Math.min(o1.length, o2.length); for (let i = 0; i < n; i++) { if (o1[i] == o2[i]) { continue ; } else { return o1[i] - o2[i]; } } return 1; }); // Printing Subset for (let i = 0; i < subset.length; i++) { for (let j = 0; j < subset[i].length; j++) { document.write(subset[i][j] + " " ); } document.write( "<br>" ); } // This code is contributed by saurabh_jaiswal. </script> |
1 1 2 1 2 3 1 3 2 2 3 3
Complexity Analysis:
- Time Complexity: O(2^n). Total number of subsets generated are 2^n, So Time Complexity is O(2^n). If we include the time taken to copy the subset vector into the res vector the time taken will be equal to the size of the subset vector.
- Auxiliary Space: O(n) There can be at max n recursion calls at a particular time, which would consume O(n) stack space.
Bit Manipulation Method
The idea is to use an n-bit integer ( from 0 to 2^n-1) whose individual bits represent whether the element(present at the ith index) of the string is included or not, the two options can be represented as:
- ‘1’ (set bit ) — denotes the element included
- ‘0’ — denotes element not included
If the ith bit in the integer is set then, append the ith element from the string for the subset.
Algorithm:
- Loop through all possible subsets using bit manipulation:
- Initialize a variable i to 0 and loop until i is less than 2n. In each iteration of the loop, increment i by 1.
- Loop through all elements of the input array:
- Check if the jth bit is set in the current subset by performing a bitwise AND operation between i and (1 << j).
- If the jth bit is set, add the jth element to the subset by printing it.
C++
#include <iostream> using namespace std; // Function to find the subsets of the given array void findSubsets( int nums[], int n) { // Loop through all possible subsets using bit manipulation for ( int i = 0; i < (1 << n); i++) { // Loop through all elements of the input array for ( int j = 0; j < n; j++) { // Check if the jth bit is set in the current subset if ((i & (1 << j)) != 0) { // If the jth bit is set, add the jth element to the subset cout << nums[j] << " " ; } } cout << endl; } } // Driver Code int main() { int arr[] = { 1, 2, 3 }; int n = sizeof (arr)/ sizeof (arr[0]); findSubsets(arr, n); } |
Java
// Java program for the above approach import java.io.*; import java.util.*; class GFG { // Function to find the subsets of // the given array public static void findSubsets( int [] nums) { // Get the length of the input array int n = nums.length; // Loop through all possible subsets // using bit manipulation for ( int i = 0 ; i < ( 1 << n); i++) { // Loop through all elements // of the input array for ( int j = 0 ; j < n; j++) { // Check if the jth bit is set // in the current subset if ((i & ( 1 << j)) != 0 ) { // If the jth bit is set, // add the jth // element to the subset System.out.print(nums[j] + " " ); } } System.out.println(); } } // Driver Code public static void main(String[] args) { int [] arr = new int [] { 1 , 2 , 3 }; findSubsets(arr); } } |
1 2 1 2 3 1 3 2 3 1 2 3
Time Complexity : O(n*(2n))
Space Complexity : O(1)
Please Login to comment...