Iterating over all subsets of a given size

怎甘沉沦 提交于 2019-12-30 10:14:31

问题


I know that iterating over all subsets of a set of size n is a performance nightmare and will take O(2^n) time.

How about iterating over all subsets of size k (for (0 <= k <= n))? Is that a performance nightmare? I know there are (n, k) = n! / k! (n - k)! possibilities. I know that if k is very close to 0 or very close to n, this is a small number.

What is the worst case performance in terms of n and k? Is there a simpler way of saying it other than just O(n! / k! (n - k)!)? Is this asymptotically smaller than O(n!) or the same?


回答1:


You want Gosper's hack:

int c = (1<<k)-1;
while (c < (1<<n)) {
  dostuff(c);
  int a = c&-c, b = c+a;
  c = (c^b)/4/a|b;
}

Explanation:

Finding the next number with as many bits set basically reduces to the case of numbers with exactly one "block of ones" --- numbers having a bunch of zeroes, then a bunch of ones, then a bunch of zeroes again in their binary expansions.

The way to deal with such a "block of ones" number is to move the highest bit left by one and slam all the others as low as possible. Gosper's hack works by finding the lowest set bit (a), finding the "high part" comprising the bits we don't touch and the "carry bit" (b), then producing a block of ones of the appropriate size that begins at the least-significant bit.




回答2:


It's easy to show that for a fixed n, (n, k) has a maximum at k = n/2. If I haven't misapplied Sterling's approximation, the asymptotic behavior for (n, n/2) is exponential.

For constant k, (n, k) is O(n^k). Keep in mind that the combinatorial function is symmetric, so it's the same for (n, n-k). It's polynomial, so it's way smaller than O(n!).



来源:https://stackoverflow.com/questions/15932237/iterating-over-all-subsets-of-a-given-size

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!