您可以递归地执行此操作,并避免重复,如果您在每次递归中保持第一个元素固定,并且仅按顺序将值分组为 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,8,9}
确保第三个元素总是在第二个元素之后,以避免重复,例如:
{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,8,9}
现在,假设在某个时刻,您选择了它作为第二组:
{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 sn-p;它返回一个包含元素组组合的 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>");