假设我有一组元素 S = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
S = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
我想创建3的组合并将其分组,以使任何数字都不会出现在多个组合中。
这是一个例子: { {3, 7, 9}, {1, 2, 4}, {5, 6, 8} }
{ {3, 7, 9}, {1, 2, 4}, {5, 6, 8} }
组中数字的顺序无关紧要,在整个示例中,组的顺序也无所谓。
简而言之,我希望原始集中的每个可能组合中都包含每个可能的组组合,但要排除出现在多个组中的数字。
我的问题:就运行时间和内存而言,这实际上可行吗?我的样本数量可能在30至50个数字之间。
如果是这样,创建此算法的最佳方法是什么?是否最好创建所有可能的组合,并仅在数字尚未出现时才选择组?
我是在Qt 5.6(基于C ++的框架)中编写的。
如果在每个递归中都将第一个元素固定不变,并且仅按值顺序排列3个组,则可以递归地执行此操作,并避免重复。
{1,2,3,4,5,6,7,8,9}
将最低元素放在第一个位置(a),并保持在该位置:
{a,b,c} = {1,,}
对于第二个点(b),迭代从第二低到第二高的每个值:
{a,b,c} = {1,2〜8,*}
对于第三个点(c),对高于第二个值的每个值进行迭代:
{1,2〜8,b + 1〜9}
然后递归其余的值。
{1,2,3} {4,5,6} {7,8,9} {1,2,3} {4,5,7} {6,8,9} {1,2,3} { 4,5,8} {6,7,9} {1,2,3} {4,5,9} {6,7,8} {1,2,3} {4,6,7} {5 ,8,9} {1,2,3} {4,6,8} {5,7,9} {1,2,3} {4,6,9} {5,7,8} {1, 2,3} {4,7,8} {5,6,9} {1,2,3} {4,7,9} {5,6,8} {1,2,3} {4,8 ,9} {5,6,7} {1,2,4} {3,5,6} {7,8,9} … {1,8,9} {2,6,7} {3 ,4,5}
我说的是“按顺序”,它不必是任何特定的顺序(数字,字母…),它可以只是输入的原始顺序。如果您确保将其余的值按收到顺序传递给下一个递归,则可以避免对每个递归的输入重新排序。
递归的贯穿过程:
假设您获得了输入{1,2,3,4,5,6,7,8,9}。作为组中的第一个元素,请从输入中获取第一个元素,对于其他两个元素,请遍历其他值:
{1,2,3} {1,2,4} {1,2,5} {1,2,6} {1,2,7} {1,2,8} {1,2,9} { 1,3,4} {1,3,5} {1,3,6} …
确保第三个元素始终位于第二个元素之后,以避免重复:
{1,3,5}⇆ {1,5,3}
现在,让我们说在某个时候,您已经选择了它作为第一组:
{1,3,7}
然后,将其余的值传递到下一个递归:
{2,4,5,6,8,9}
在此递归中,您将应用与第一个组相同的规则:将第一个元素作为组中的第一个元素并将其保留在该位置,然后遍历第二个和第三个元素的其他值:
{2,4,5} {2,4,6} {2,4,8} {2,4,9} {2,5,6} {2,5,8} {-2,5,9-} { 2,6,7} …
现在,假设在某个时候,您已经选择了它作为第二组:
{2,5,6}
{4,8,9}
而且由于这是最后一组,所以只有一种可能性,因此这种特殊的递归将以这种组合结束:
{1,3,7} {2,5,6} {4,8,9}
如您所见,您无需在任何时候对值进行排序,只要您按照对它们的接收顺序将它们传递到下一个递归即可。因此,如果您收到例如:
{q,w,e,r,t,y,u,i,o}
然后从中选择组:
{q,r,u}
那么您应该继续:
{w,e,t,y,i,o}
这是一个演示该方法的JavaScript代码段;它返回包含元素组组合的3D数组。 (过滤器函数创建输入数组的副本,其中元素0,i和j被删除。)
function clone2D(array) { var clone = []; for (var i = 0; i < array.length; i++) clone.push(array[i].slice()); return clone; } function groupThree(input) { var result = [], combination = []; group(input, 0); return result; function group(input, step) { combination[step] = [input[0]]; for (var i = 1; i < input.length - 1; i++) { combination[step][1] = input[i]; for (var j = i + 1; j < input.length; j++) { combination[step][2] = input[j]; if (input.length > 3) { var rest = input.filter(function(elem, index) { return index && index != i && index != j; }); group(rest, step + 1); } else result.push(clone2D(combination)); } } } } var result = groupThree([1,2,3,4,5,6,7,8,9]); for (var r in result) document.write(JSON.stringify(result[r]) + "<br>");