【发布时间】:2013-04-10 17:12:19
【问题描述】:
我知道迭代一组大小为 n 的所有子集是一场性能噩梦,需要 O(2^n) 时间。
如何迭代所有大小为 k 的子集(对于 (0
就 n 和 k 而言,最差情况下的性能是多少?除了O(n!/ k!(n - k)!)之外,还有更简单的说法吗?这是渐近小于 O(n!) 还是一样?
【问题讨论】:
-
显然,这取决于
n和k的值。你在寻找什么样的答案?
我知道迭代一组大小为 n 的所有子集是一场性能噩梦,需要 O(2^n) 时间。
如何迭代所有大小为 k 的子集(对于 (0
就 n 和 k 而言,最差情况下的性能是多少?除了O(n!/ k!(n - k)!)之外,还有更简单的说法吗?这是渐近小于 O(n!) 还是一样?
【问题讨论】:
n 和k 的值。你在寻找什么样的答案?
你想要 Gosper 的破解:
int c = (1<<k)-1;
while (c < (1<<n)) {
dostuff(c);
int a = c&-c, b = c+a;
c = (c^b)/4/a|b;
}
解释:
找到设置了尽可能多的位的下一个数字基本上可以简化为只有一个“1 块”的数字的情况 --- 数字有一堆零,然后是一堆一,然后又是一堆零他们的二进制扩展。
处理这样一个“1 块”数字的方法是将最高位向左移动一位,并将所有其他位尽可能低。 Gosper 的破解方法是找到最低设置位 (a),找到包含我们不接触的位和“进位位”(b) 的“高位”,然后生成一组适当的位从最低有效位开始的大小。
【讨论】:
很容易证明,对于固定的n,(n, k) 的最大值为k = n/2。如果我没有误用 Sterling 的近似值,(n, n/2) 的渐近行为是指数的。
对于常量k,(n, k) 是O(n^k)。请记住,组合函数是对称的,因此(n, n-k) 也是如此。它是多项式,所以它比O(n!) 小。
【讨论】: