I want to generate all the subsets of size k from a set.
eg:-say I have a set of 6 elements, I have to list all the subsets in which the cardinality of elements is 3
Here's some pseudocode. You can cut same recursive calls by storing the values for each call as you go and before recursive call checking if the call value is already present.
The following algorithm will have all the subsets excluding the empty set.
list * subsets(string s, list * v){
if(s.length() == 1){
list.add(s);
return v;
}
else
{
list * temp = subsets(s[1 to length-1], v);
int length = temp->size();
for(int i=0;i<length;i++){
temp.add(s[0]+temp[i]);
}
list.add(s[0]);
return temp;
}
}
The Problem can be solved using recursion. We need to consider the following cases for recursion.
Following is a C++ program that demonstrates the above Algorithm.
#include<iostream>
#include<cstdio>
using namespace std;
void KSubset(int *a,int n,int *s,int sindex,int index,int k){
if (index>n)
return;
if (k==0){
for(int i=0;i<sindex;i++)
printf(" %d ",s[i]);
printf("\n");
return ;
}
s[sindex]=a[index];
KSubset(a,n,s,sindex+1,index+1,k-1);
KSubset(a,n,s,sindex,index+1,k);
}
int main(){
int a[]={1,2,3,4,5};
int s[3];
KSubset(a,5,s,0,0,3);
return 0;
}
Initialize a bit array with (1<<nbits)-1
and then use this algorithm:
http://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
For sets larger than the maximum integer size, you can still apply the same algorithm to your own type.
#include <stdio.h>
#define FIN "subsets.in"
#define FOUT "subsets.out"
#define MAXSIZE 100
void performSubsets(int n, int k){
int i, j, s, v[ MAXSIZE ];
freopen(FOUT, "w", stdout);
memset(v, 0, sizeof( v ));
do {
v[ n - 1 ]++;
for(i = n - 1; i >= 1; i--) {
if(v[ i ] > 1) {
v[ i ] -= 2;
v[ i - 1 ] += 1;
}
}
s = 0;
for(j = 0; j < n; j++) s += v[j];
for(j = 0; j < n; j++)
if( v[ j ] && s == k) printf("%d ", (j + 1));
if(s == k) printf("\n");
} while(s < n);
fclose( stdout );
}
int main() {
int n, k;
freopen(FIN, "r", stdin);
//read n and size k
scanf("%d %d", &n, &k);
fclose( stdin );
performSubsets(n,k);
}
This problem can be solved using an algorithm non-recursive.
#include <cstdio>
void g(int s[],int p,int k,int t[],int q=0,int r=0)
{
if(q==k)
{
for(int i=0;i<k;i++)
printf("%d ",t[i]);
printf("\n");
}
else
{
for(int i=r;i<p;i++)
{
t[q]=s[i];
g(s,p,k,t,q+1,i+1);
}
}
}
main()
{
int s[]={1,2,3,4,5},t[5];
g(s,5,3,t);
}
Find a working code below
#include<iostream>
#include<string>
#include<list>
using namespace std;
void print( list<int> l){
for(list<int>::iterator it=l.begin(); it!=l.end() ; ++it)
cout << " " << *it;
cout<<endl;
}
void subset(int arr[], int size, int left, int index, list<int> &l){
if(left==0){
print(l);
return;
}
for(int i=index; i<size;i++){
l.push_back(arr[i]);
subset(arr,size,left-1,i+1,l);
l.pop_back();
}
}
int main(){
int array[5]={1,2,3,4,5};
list<int> lt;
subset(array,5,3,0,lt);
return 0;
}