Find all distinct subsets of a given set using BitMasking Approach
Last Updated :
11 Aug, 2023
Given an array of integers arr[], The task is to find all its subsets. The subset can not contain duplicate elements, so any repeated subset should be considered only once in the output.
Examples:
Input: S = {1, 2, 2}
Output: {}, {1}, {2}, {1, 2}, {2, 2}, {1, 2, 2}
Explanation: The total subsets of given set are – {}, {1}, {2}, {2}, {1, 2}, {1, 2}, {2, 2}, {1, 2, 2}
Here {2} and {1, 2} are repeated twice so they are considered only once in the output
Input: S = {1, 2}
Output: {}, {1}, {2}, {1, 2}
Explanation: The total subsets of given set are – {}, {1}, {2}, {1, 2}
BRUTE METHOD:
Intuition:
- We do this problem by using the backtracking approach.
- we declare a arraylist to store all the subsets generated.
- We sort the array in order to skip repeated subsets as it should be unique.
- then we pick a particular element or not pick from the array and we generate the subsets.
- atlast we add it in the final list and return it.
Implementation:
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void findSubsets( int ind, vector< int >& nums, vector< int >& ds, vector<vector< int >>& ansList) {
ansList.push_back(ds);
for ( int i = ind; i < nums.size(); i++) {
if (i != ind && nums[i] == nums[i - 1])
continue ;
ds.push_back(nums[i]);
findSubsets(i + 1, nums, ds, ansList);
ds.pop_back();
}
}
vector<vector< int >> AllSubsets( int arr[], int n) {
vector< int > nums(arr, arr + n);
vector< int > ds;
sort(nums.begin(), nums.end());
vector<vector< int >> ansList;
findSubsets(0, nums, ds, ansList);
return ansList;
}
int main() {
int set[] = { 10, 12, 12 };
vector<vector< int >> subsets = AllSubsets(set, 3);
for ( auto subset : subsets) {
cout << "[" ;
for ( int i = 0; i < subset.size(); i++) {
cout << subset[i];
if (i < subset.size() - 1) {
cout << ", " ;
}
}
cout << "], " ;
}
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static void
findSubsets( int ind, int [] nums, ArrayList<Integer> ds,
ArrayList<ArrayList<Integer> > ansList)
{
ansList.add( new ArrayList<>(ds));
for ( int i = ind; i < nums.length; i++) {
if (i != ind && nums[i] == nums[i - 1 ])
continue ;
ds.add(nums[i]);
findSubsets(i + 1 , nums, ds, ansList);
ds.remove(ds.size() - 1 );
}
}
public static ArrayList<ArrayList<Integer> >
AllSubsets( int arr[], int n)
{
Arrays.sort(arr);
ArrayList<ArrayList<Integer> > ansList
= new ArrayList<>();
findSubsets( 0 , arr, new ArrayList<>(), ansList);
return ansList;
}
public static void main(String[] args)
{
int [] set = { 10 , 12 , 12 };
System.out.println(AllSubsets(set, 3 ));
}
}
|
Python3
def find_subsets(ind, nums, ds, ans_list):
ans_list.append( list (ds))
for i in range (ind, len (nums)):
if i ! = ind and nums[i] = = nums[i - 1 ]:
continue
ds.append(nums[i])
find_subsets(i + 1 , nums, ds, ans_list)
ds.pop()
def all_subsets(arr):
nums = sorted (arr)
ans_list = []
find_subsets( 0 , nums, [], ans_list)
return ans_list
if __name__ = = "__main__" :
set = [ 10 , 12 , 12 ]
subsets = all_subsets( set )
for subset in subsets:
print (subset, end = ", " )
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static void FindSubsets( int ind, int [] nums, List< int > ds, List<List< int >> ansList)
{
ansList.Add( new List< int >(ds));
for ( int i = ind; i < nums.Length; i++)
{
if (i != ind && nums[i] == nums[i - 1])
continue ;
ds.Add(nums[i]);
FindSubsets(i + 1, nums, ds, ansList);
ds.RemoveAt(ds.Count - 1);
}
}
static List<List< int >> AllSubsets( int [] arr)
{
Array.Sort(arr);
List<List< int >> ansList = new List<List< int >>();
FindSubsets(0, arr, new List< int >(), ansList);
return ansList;
}
public static void Main()
{
int [] set = { 10, 12, 12 };
List<List< int >> subsets = AllSubsets( set );
foreach (List< int > subset in subsets)
{
Console.Write( "[" );
for ( int i = 0; i < subset.Count; i++)
{
Console.Write(subset[i]);
if (i < subset.Count - 1)
{
Console.Write( ", " );
}
}
Console.Write( "], " );
}
}
}
|
Javascript
function findSubsets(ind, nums, ds, ansList) {
ansList.push([...ds]);
for (let i = ind; i < nums.length; i++) {
if (i !== ind && nums[i] === nums[i - 1]) {
continue ;
}
ds.push(nums[i]);
findSubsets(i + 1, nums, ds, ansList);
ds.pop();
}
}
function allSubsets(arr) {
const nums = arr.slice().sort((a, b) => a - b);
const ansList = [];
findSubsets(0, nums, [], ansList);
return ansList;
}
const set = [10, 12, 12];
const subsets = allSubsets(set);
for (const subset of subsets) {
console.log(subset);
}
|
Output[[], [10], [10, 12], [10, 12, 12], [12], [12, 12]]
Time Complexity: O(2^N * N) since we are generating every subset
Auxiliary Space: O(2^N)
Prerequisite: Power Set
Approach: Below is the idea to solve the problem:
The idea is to use a bit-mask pattern to generate all the combinations as discussed in post. To avoid printing duplicate subsets construct a string out of given subset such that subsets having similar elements will result in same string. Maintain a list of such unique strings and finally decode all such string to print its individual elements.
Illustration :
S = {1, 2, 2}
The binary digits from 0 to 7 are
0 –> 000 –> number formed with no setbits –> { }
1 –> 001 –> number formed with setbit at position 0 –> { 1 }
2 –> 010 –> number formed with setbit at position 1 –> { 2 }
3 –> 011 –> number formed with setbit at position 0 and 1 –> { 1 , 2 }
4 –> 100 –> number formed with setbit at position 2 –> { 2 }
5 –> 101 –> number formed with setbit at position 0 and 2 –> { 1 , 2}
6 –> 110 –> number formed with setbit at position 1 and 2 –> { 2 , 2}
7 –> 111 –> number formed with setbit at position 0 , 1 and 2 –> {1 , 2 , 2}
After removing duplicates final result will be { }, { 1 }, { 2 }, { 1 , 2 }, { 2 , 2 }, { 1 , 2 , 2}
Note: This method will only work on sorted arrays.
Follow the below steps to Implement the idea:
- Initialize a variable pow_set_size as 2 raise to size of array and a vector of vector ans to store all subsets.
- Iterate over all bitmasks from 0 to pow_set_size – 1.
- For every bitmask include the elements of array of indices where bits are set into a subset vector.
- If this subset doesn’t already exist then push the subset in the ans vector.
- Return ans.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
vector<vector< int > > findPowerSet(vector< int >& nums)
{
int bits = nums.size();
unsigned int pow_set_size = pow (2, bits);
sort(nums.begin(), nums.end());
vector<vector< int > > ans;
vector<string> list;
for ( int counter = 0; counter < pow_set_size;
counter++) {
vector< int > subset;
string temp = "" ;
for ( int j = 0; j < bits; j++) {
if (counter & (1 << j)) {
subset.push_back(nums[j]);
temp += to_string(nums[j]) + '$' ;
}
}
if (find(list.begin(), list.end(), temp)
== list.end()) {
ans.push_back(subset);
list.push_back(temp);
}
}
return ans;
}
int main()
{
vector< int > arr{ 10, 12, 12 };
vector<vector< int > > power_set = findPowerSet(arr);
for ( int i = 0; i < power_set.size(); i++) {
for ( int j = 0; j < power_set[i].size(); j++)
cout << power_set[i][j] << " " ;
cout << endl;
}
return 0;
}
|
Java
import java.io.*;
import java.util.*;
public class GFG {
static void printPowerSet( int [] set, int set_size)
{
ArrayList<String> subset = new ArrayList<String>();
long pow_set_size = ( long )Math.pow( 2 , set_size);
int counter, j;
for (counter = 0 ; counter < pow_set_size;
counter++) {
String temp = "" ;
for (j = 0 ; j < set_size; j++) {
if ((counter & ( 1 << j)) > 0 )
temp
+= (Integer.toString(set[j]) + '$' );
}
if (!subset.contains(temp)
&& temp.length() > 0 ) {
subset.add(temp);
}
}
for (String s : subset) {
s = s.replace( '$' , ' ' );
System.out.println(s);
}
}
public static void main(String[] args)
{
int [] set = { 10 , 12 , 12 };
printPowerSet(set, 3 );
}
}
|
Python3
def printPowerSet(arr, n):
_list = []
for i in range ( 2 * * n):
subset = ""
for j in range (n):
if (i & ( 1 << j)) ! = 0 :
subset + = str (arr[j]) + "|"
if subset not in _list and len (subset) > 0 :
_list.append(subset)
for subset in _list:
arr = subset.split( '|' )
for string in arr:
print (string, end = " " )
print ()
if __name__ = = '__main__' :
arr = [ 10 , 12 , 12 ]
n = len (arr)
printPowerSet(arr, n)
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static void printPowerSet( int [] set , int set_size)
{
List< string > subset = new List< string >();
long pow_set_size = ( long )Math.Pow(2, set_size);
int counter, j;
for (counter = 0; counter < pow_set_size;
counter++) {
string temp = "" ;
for (j = 0; j < set_size; j++) {
if ((counter & (1 << j)) > 0)
temp
+= (Convert.ToString( set [j]) + ' ' );
}
if (!subset.Contains(temp) && temp.Length > 0) {
subset.Add(temp);
}
}
foreach ( string s in subset)
{
s.Replace( '$' , ' ' );
Console.WriteLine(s);
}
}
public static void Main( string [] args)
{
int [] set = { 10, 12, 12 };
printPowerSet( set , 3);
}
}
|
Javascript
<script>
const findPowerSet = (nums) => {
let bits = nums.length;
let pow_set_size = Math.pow(2, bits);
nums.sort();
let ans = [];
let list = [];
for (let counter = 0; counter < pow_set_size; counter++) {
let subset = [];
let temp = "" ;
for (let j = 0; j < bits; j++) {
if (counter & (1 << j)) {
subset.push(nums[j]);
temp += nums[j].toString() + '$' ;
}
}
if (list.indexOf(temp) == -1) {
ans.push(subset);
list.push(temp);
}
}
return ans;
}
let arr = [10, 12, 12];
let power_set = findPowerSet(arr);
for (let i = 0; i < power_set.length; i++) {
for (let j = 0; j < power_set[i].length; j++)
document.write(`${power_set[i][j]} `);
document.write( "<br/>" );
}
</script>
|
Output10
12
10 12
12 12
10 12 12
Time Complexity: O(N*2N)
Auxiliary Space: O(N*N)
Analysis:
If is the total number of steps in the code, then the loop to generate all binary combinations runs till, and then the inner loop run till log(i).
Hence, , Raising to the power of two on both sides
Using log on both sides and applying Sterling’s approximation,
Hence the time complexity is
Find all distinct subsets of a given set using BitMasking Approach using Backtracking
Refer to the article https://www.geeksforgeeks.org/backtracking-to-find-all-subsets/ to solve the problem using the backtracking approach.
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.GeeksforGeeks.org or mail your article to contribute@GeeksforGeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Share your thoughts in the comments
Please Login to comment...