generate all subsets of size k from a set

后端 未结 9 1334
南旧
南旧 2020-12-08 03:30

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

相关标签:
9条回答
  • 2020-12-08 04:16

    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)));
    }
    
    0 讨论(0)
  • 2020-12-08 04:18

    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.

    0 讨论(0)
  • 2020-12-08 04:18

    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;
    }
    
    0 讨论(0)
提交回复
热议问题