Algorithm 生成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),也称为弗兰克·格雷之后的格雷码, 是一种二进制数字系统,其中两个连续值仅在一位上不同 如果我们只使用灰色

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)中实现发电机


我知道,如果迭代,返回的列表无论如何都会有一个O(n)运行时。

增量和格雷码解决方案都是O(1)摊销的,我相信这和您将得到的一样好。“摊销O(1)”意味着您偶尔会获得更长的单次调用时间,但它们非常罕见,
k
连续调用的总时间为O(k),因此一次调用的平均时间为O(1)

这是一个比“预期O(1)”更强的说法,因为摊销执行时间是对足够调用的聚合保证,而如果您非常不走运,预期执行时间可能会产生意外的聚合时间。(在实践中,这种差异通常并不重要,但请参见,例如,针对“预期O(1)”哈希表查找的DoS攻击。)

要了解增量算法为何摊销为O(1),请查看每次迭代中翻转的位数。每隔一次迭代(数字以0结尾),正好翻转一位。每四次迭代,正好有两位被翻转。每第八次迭代,正好有三位被翻转。等等很容易看出,在
k
迭代中,将翻转
2k+log2k
位的最大总数

对于格雷码算法,每次迭代仅翻转一位,但必须找到该位。格雷码增量的一个简单迭代实现是保持当前选择的奇偶性。由于奇偶校验在每次迭代中都会发生变化,因此无需重新计算;它是简单的倒置。然后,算法在两个规则之间交替:

  • 如果奇偶校验为偶数,则翻转低阶位

  • 如果奇偶校验为奇数,则将该位翻转到最低阶1位的左侧

  • 显然,选项1适用于一半的迭代,并且它只检查一位。对于选项2,我们需要计算每次迭代检查多少位。由于每种可能的位组合只出现一次,因此尾随零的数量遵循与递增整数序列相同的频率:每秒没有尾随零,每四次有一个,每八次有两个,依此类推

    因此,最后,我们检查两种解决方案中相同数量的低阶位。但是,格雷码解决方案在每次迭代中只更改集合的一个元素,而增量解决方案更改两个的摊销平均值。因此,如果集合修改代价高昂,则格雷码算法可能更为优越


    事后思考
  • 您可以直接将格雷码算法应用于集合,而无需传递位字符串,但其性能将取决于集合实现的某些细节。奇偶校验继续如上所述交替进行(它也是集合模2的大小,因此如果集合具有o(1)大小操作,则可以使用该操作而不是保持状态)。我们假设您有一些o(1)函数,将每个可能的集合元素映射到其后续元素(在宇宙中,而不是在选择中),这可能类似于位映射到集合元素的方式。然后,两种可能的算法操作是:

  • 偶数奇偶:如果集合中最小的元素是宇宙中最小的元素,则移除该元素;否则添加它

  • 奇数奇偶校验:如果集合中最小元素的后继元素也存在,则将其移除;否则,添加它

  • 如果您需要在每次迭代中创建一个新集,而不是修改当前选择集,那么您当然不能做得比O(n)更好,因为选择的摊销平均大小是n/2,并且创建一个集所需的时间不能少于其大小


  • 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
    。稍微