-1

For a set of k-elements, I need to find all possible n-element subsets (n < k).

How should I approach this problem?

Just a suggestion will be helpful Thanks!

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
user1315305
  • 1,329
  • 2
  • 11
  • 20
  • 4
    `How should I approach this problem.` Pen and paper works best when thinking about algorithms. – Nico Jul 02 '13 at 20:15
  • @user1315305 question marked -ve because wrong tags, question is typical for me as well – Grijesh Chauhan Jul 02 '13 at 20:25
  • @user1315305 You're very welcome. This is usually my answer when I see about zero effort put in. – Nico Jul 02 '13 at 20:25
  • 2
    @user1315305 there is not good solution but [an old similar question](http://stackoverflow.com/questions/4098248/how-to-generate-all-k-elements-subsets-from-an-n-elements-set-recursively-in-jav) – Grijesh Chauhan Jul 02 '13 at 20:34
  • Please don't vote to close this question, its a good question from algorithm I am also looking for some answers. – Grijesh Chauhan Jul 02 '13 at 20:36
  • possible duplicate of [Algorithm to return all combinations of k elements from n](http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n) – David Eisenstat Aug 02 '13 at 12:35

3 Answers3

4

I saw this in topcoder's algorithm tutorials.Take some time and understand how it works.

Iterate through all k-element subsets of {0, 1, … N-1}

   int s = (1 << k) - 1;
   while (!(s & 1 << N))
   {
     // do stuff with s
     int lo = s & ~(s - 1);       // lowest one bit
     int lz = (s + lo) & ~s;      // lowest zero bit above lo
     s |= lz;                     // add lz to the set
     s &= ~(lz - 1);              // reset bits below lz
     s |= (lz / lo / 2) - 1;      // put back right number of bits at end
   }
Aravind
  • 3,169
  • 3
  • 23
  • 37
  • 1
    While it is usually extremely efficient, bit magic is a poor way to communicate algorithmic ideas. – G. Bach Jul 02 '13 at 21:18
  • @G.Bach: Probably better to communicate the algorithm that solves the problem quickly than the algorithm that solves the problem slowly. Especially when you comment it so that it's comprehensible. No? – tmyklebu Jul 02 '13 at 23:04
  • @tmyklebu Sure, the algorithm with better complexity is preferable, and comments do help. But while I know what this code is supposed to achieve, I don't understand how it works. – G. Bach Jul 03 '13 at 11:45
  • @G.Bach: Did you try? I'll read the code and the comments: `lo` is the lowest set bit. `lz` is the lowest unset bit above it. Consequently, `lz / lo - 1` has only its lowest `log2(lz) - log2(lo)` bits set. That's one too many, so pick off the low bit by dividing by two. Set `lz`, clear everything below `lz`, then set the right number of bits at the bottom of the number. – tmyklebu Jul 03 '13 at 16:29
  • Sorry for my question, but how can I use this code in practice? What does 's' stand for? – user1315305 Jul 03 '13 at 18:55
  • 1
    @user1315305: s is the bitmask that represents the current k-element subset.For example it could be "1000" which means first element is present, all others are absent. – Aravind Jul 03 '13 at 19:18
  • I noticed that it doesn't work for example when k = 21, N = 40. Why? – user1315305 Jul 03 '13 at 20:14
  • 1
    That's because int can store only 32 bits.So for N>32, you need to use long long which can store 64 bits. – Aravind Jul 04 '13 at 05:11
  • Ok, so I guess I will have to use BigInteger in Java. Thanks. – user1315305 Jul 04 '13 at 05:34
2

When I needed to get all combinations (or subsets) of an ArrayList of Strings in Java, I used this method.

public static List<List<String>> powerset(ArrayList<String> list) {
        List<List<String>> ps = new ArrayList<List<String>>();
        ps.add(new ArrayList<String>());

        // for every item in the original list
        for (String item : list) {
            List<List<String>> newPs = new ArrayList<List<String>>();

            for (List<String> subset : ps) {
                // copy all of the current powerset's subsets
                newPs.add(subset);

                // plus the subsets appended with the current item
                List<String> newSubset = new ArrayList<String>(subset);
                newSubset.add(item);
                newPs.add(newSubset);
            }

            // powerset is now powerset of list.subList(0, list.indexOf(item)+1)
            ps = newPs;
        }
        return ps;
}

It's an expensive operation and probably not the perfect solution for your situation. But if I were trying to come up with a solution quickly, I would do something along these lines. You can check to see if the newSubset was less than n, the size of the subsets you want, and only add item to it if it is less than n. This would stop you from generating subset greater than n. At the end, you could iterate through ps and remove any arraylist that is less than n. Again, this solution is in no way perfect....but it should do the trick

mistahenry
  • 8,554
  • 3
  • 27
  • 38
  • I like this combinatorial approach, and considering it's a power set you're constructing, it does not look too bad to me. But if the job is only to get the subsets with a fixed number of elements, constructing the power set is exponentially more expensive. – G. Bach Jul 02 '13 at 20:53
  • Unfortunately I run out of memory for subset size = 21, and set size = 60 so I have to find some better solution. – user1315305 Jul 03 '13 at 18:52
0

Sentence: Set A is set of whole numbers less than 10.

Written As:

A={0,1,2,3,4,5,6,7,8,9}

it is called listing or roster method

Lucifer
  • 29,392
  • 25
  • 90
  • 143
Chloe
  • 1