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
My old code gives the following result:
111000
110100
110010
110001
101100
101010
101001
100110
100101
100011
011100
011010
011001
010110
010101
010011
001110
001101
001011
000111
Enough optimized:
#include <iostream>
int firstPermutation(int n, int k) {
return ((1 << k) - 1) << (n - k);
}
int shiftLast1(int a) {
return (a - 1) ^ ((a^(a - 1)) >> 2);
}
int add1AfterLast1(int a) {
return a | (((a^(a - 1)) + 1) >> 2);
}
int nextPermutation(int a) {
if ((a & (a + 1)) == 0) {
return 0;
}
if (a & 1) {
return add1AfterLast1(nextPermutation(a >> 1) << 1);
}
else {
return shiftLast1(a);
}
}
int main() {
int n = 6;
int k = 3;
int a = firstPermutation(n, k);
do {
for (int i = 0; i < n; i++) {
std::cout << ((a >> (n - 1 - i)) & 1);
}
std::cout << std::endl;
} while ((a = nextPermutation(a)));
}
The most intuitive algorithm would indeed use recursion. When you have a set, we will assume you can iterate over all its elements.
If I call tail(e) a set of all the elements after element e.
Thus I want right now combinations(s,k)
loop over each element in s and get e :: combinations(tail(e), k-1) where :: means "concatenated to each of"
Of course sometimes there will be no such combinations (you are off the end of the list).
You just need a master collection (set of sets) to add your combinations to and a way to create
So assuming we have no globals anywhere we can have something like:
getCombinations( headset [in], tailset [in], count [in], output [append] )
headset or tailset could be empty. count could be 0, in which case we write "headset" to output (the base condition) otherwise we iterate through each element in tailset, adding it (locally) to headset, make tailset (locally) the tail of our element, subtract 1 from count and "recurse" by calling the function.
Here is an Iterative solution :
#include <stdio.h>
#include <stdlib.h>
void printer(int locations[],int a[],int r)
{
int i;
for(i=0; i<r; i++)
{
int x=locations[i];
printf("%d ",a[x]);
}
printf("\n");
}
int main()
{
int a[100000];
int locations[1000];
int i,n,r;
printf("Enter N: ");
scanf("%d",&n);
printf("Enter K: ");
scanf("%d",&r);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0; i<r; i++)
locations[i]=i;
printer(locations,a,r);
while(locations[0]<n-r)
{
for(i=r-1; i>0; i--)
{
if(locations[i-1]<n-r+i-1)
{
if(locations[i]<n-r+i)
{
locations[i]++;
printer(locations,a,r);
break;
}
else
{
locations[i-1]++;
int j;
for(j=i; j<r; j++)
{
locations[j]=locations[j-1]+1;
}
printer(locations,a,r);
break;
}
}
}
}
return 0;
}