0

This is a very classic problem and most of the solutions I found use the recursion approach like this. Since there are Cn,k combinations, I was wondering if there exists an algorithm that can print all the combinations in O(n*Cn,k) time. I think the answer given in the link takes more time than this. Also, is there an algorithm that can print the results without using additional space(I mean, without additional space that is dependent on n and k. O(1) is surely OK)?

Thanks.

Community
  • 1
  • 1
eaglesky
  • 650
  • 2
  • 12
  • 27
  • The question you linked provides the answer you are looking for. Why do you think it is inefficient? It does not perform any unnecessary recursions. – Abhishek Bansal Jul 31 '14 at 07:39
  • possible duplicate of [Find all subsets of length k in an array](http://stackoverflow.com/questions/12548312/find-all-subsets-of-length-k-in-an-array) – Abhishek Bansal Jul 31 '14 at 07:40
  • @user1990169: That algorithm will return the combinations when (current.size() < k) and (idx == superSet.size()), which are unnecessary, I think. – eaglesky Jul 31 '14 at 07:47

2 Answers2

1

The algorithm linked is giving you all of the permutations as quickly as possible -- O(n!/k!) -- which is slow, because there are exponentially many permutations.

To get all of the combinations in O(Cn,k) time, you can use one of the algorithms in answers to this other question: Algorithm to return all combinations of k elements from n.

Community
  • 1
  • 1
Patrick Collins
  • 9,307
  • 4
  • 23
  • 60
1

Just a simple javascript code to test from windows command line (cscript test.js).

This is nothing more than a sum with carry where the "digits" are the position of the element in the set.

No recursion and only needs to store the set elements and the array to hold the current subset.

// define the initial set
var set = 'abcdefg'.split('');
var setLength = set.length;

// define the subset length and initialize the first subset
var subsetLength = 5;
var aSubset = new Array(subsetLength+1);

var i;
    for( i = 0 ; i < subsetLength ; i++ ) aSubset[i]=i;

// place a guard at the end
    aSubset[subsetLength] = setLength;

// generate each of the posible subsets 
// This is just a sum with carry where the value of each of the "digits" 
// is in the range [i..subset[i+1])
var r = 0, start = 0;
    do {
        // print the subset
        for( i = 0 ; i < subsetLength ; i++ ) {
            WScript.StdOut.Write( set[aSubset[i]] );
        };
        WScript.StdOut.WriteLine('');

        // calculate the next subset
        for( i = start, r = 1 ; i < subsetLength ; i++ ) {
            aSubset[i]++;
            if (aSubset[i] < aSubset[i+1]) { 
                start = ( i==0 ? 0 : i-1 ); 
                r = 0; 
                break; 
            } else { 
                aSubset[i] = i 
            };
        };
    } while (r == 0);
MC ND
  • 65,671
  • 6
  • 67
  • 106