查看您对原始帖子的评论,您需要一个迭代解决方案。当您拥有支持尾调用优化的语言时,递归解决方案将与迭代解决方案一样快。但是,如果您使用的是 Java/C#,这又是不可用的,所以这里有另一种看待问题的方法。
您正在生成组合。组合只是具有一定数量元素的子集。具有小集的子集可以用位掩码表示。
如果我有集合[1, 2, 3, 4]
并且我想描述子集[1, 3, 4]
,我可以通过遍历每个元素并询问“True or False: is this element in the subset?”来做到这一点。所以,对于[1, 3, 4]
,结果是[True, False, True, True]
。如果我使用小于 32(或 64)字节的集合,我可以将其编码为整数:1011b = 11。这在内存中非常紧凑,并且计算机往往具有非常快速的位数学运算符。
那么,就这些二进制数而言,什么是组合呢?如果我想要所有具有 N 个成员的子集,我可以将其翻译为“我想要所有具有 N 位设置的数字”。
像[1, 2, 3, 4]
我们一样。我们想要所有具有 3 个元素的子集。恰好设置了 3 位的 4 位数字有多少?答案:1110b、1101b、1011b 和 0111b。如果我们将这些整数转换为子集,我们会得到您的解:[1, 2, 3]
、[1, 2, 4]
、[1, 3, 4]
和[2, 3, 4]
。
您可以开始仅考虑位。您从设置了 N 位的最小数字开始。这对应于一个解决方案。然后,您开始一对一地翻转位。以一种系统的方式,使得每次迭代总是产生下一个最高的数字。