Algorithm 生成o(1)中集合的所有组合
int{1,2,3}集合的组合为: {},{1},{2},{1,2},{3},{1,3},{2,3},{1,2,3} 常见的解决方案是跟踪索引的代表位掩码 从我的0-7中的数字示例: 000001010011100101110111 该算法允许迭代求解, 每次生成器检查每个位并决定是否插入该项时, 因此,它创建了运行时为O(n)的下一个组合 灰色代码:(来自维基百科) 反射二进制码(RBC),也称为弗兰克·格雷之后的格雷码, 是一种二进制数字系统,其中两个连续值仅在一位上不同 如果我们只使用灰色数字,我们得到的数字范围如下: 0000010101111101100 结果按不同顺序相同: {},{1},{1,2},{2},{2,3},{1,2,3},{1,3},{3} 但这里我们看到的区别只是一项。 是否可以使用格雷码范围在O(1)中实现发电机Algorithm 生成o(1)中集合的所有组合,algorithm,generator,combinations,pseudocode,gray-code,Algorithm,Generator,Combinations,Pseudocode,Gray Code,int{1,2,3}集合的组合为: {},{1},{2},{1,2},{3},{1,3},{2,3},{1,2,3} 常见的解决方案是跟踪索引的代表位掩码 从我的0-7中的数字示例: 000001010011100101110111 该算法允许迭代求解, 每次生成器检查每个位并决定是否插入该项时, 因此,它创建了运行时为O(n)的下一个组合 灰色代码:(来自维基百科) 反射二进制码(RBC),也称为弗兰克·格雷之后的格雷码, 是一种二进制数字系统,其中两个连续值仅在一位上不同 如果我们只使用灰色
我知道,如果迭代,返回的列表无论如何都会有一个O(n)运行时。增量和格雷码解决方案都是O(1)摊销的,我相信这和您将得到的一样好。“摊销O(1)”意味着您偶尔会获得更长的单次调用时间,但它们非常罕见,
k
连续调用的总时间为O(k),因此一次调用的平均时间为O(1)
这是一个比“预期O(1)”更强的说法,因为摊销执行时间是对足够调用的聚合保证,而如果您非常不走运,预期执行时间可能会产生意外的聚合时间。(在实践中,这种差异通常并不重要,但请参见,例如,针对“预期O(1)”哈希表查找的DoS攻击。)
要了解增量算法为何摊销为O(1),请查看每次迭代中翻转的位数。每隔一次迭代(数字以0结尾),正好翻转一位。每四次迭代,正好有两位被翻转。每第八次迭代,正好有三位被翻转。等等很容易看出,在k
迭代中,将翻转2k+log2k
位的最大总数
对于格雷码算法,每次迭代仅翻转一位,但必须找到该位。格雷码增量的一个简单迭代实现是保持当前选择的奇偶性。由于奇偶校验在每次迭代中都会发生变化,因此无需重新计算;它是简单的倒置。然后,算法在两个规则之间交替:
事后思考
O(1)算法的输出必须具有恒定的大小。您建议使用哪一个常量?@n.m.我正在考虑返回一个只读子集合。您要返回的内容必须是常量。您能在恒定大小的内存中表示子集合吗?常数是什么?顺便说一句,
o(1)
(不是o(1)
)的值会随着n
变大而减小。@n.m.一个双链接列表会在这里起作用。也许字典牙齿看起来是个好答案,但我不明白(2)——如果x是1001
,那么将该位翻转到最低顺序1位的左边,就会得到1011
。然后重复将再次给出1001
。@PaulHankin:您是否阅读了使用奇偶校验来决定使用(1)和(2)中哪一个的部分?您从未连续应用(1)或(2)两次。事实上,1001
甚至具有奇偶校验,因此可以翻转低位,1000
。它具有奇偶校验,因此您可以移动到11000
。偶数奇偶校验,11001
。奇数奇偶校验,11011
。甚至11010
。奇数11110
。稍微