给定Y个数,得到X个数的每个组合?
Posted
技术标签:
【中文标题】给定Y个数,得到X个数的每个组合?【英文标题】:Getting every combination of X numbers given Y numbers? 【发布时间】:2017-06-30 01:36:50 【问题描述】:我遇到了一个数学问题,我无法对逻辑进行编程。
让我用一个例子来解释一下:
假设我有 4 个洞和 3 个弹珠,这些洞是有序的,而我的弹珠是 A、B 和 C,也是有序的。
我需要获得所有可能的 ORDERED 组合:
ABC4
AB3C
A2BC
1ABC
这很简单,但是如果孔的数量发生变化怎么办?假设现在我有 5 个洞。
ABC45
AB3C5
A2BC5
1ABC5
AB34C
A2B4C
1AB4C
A23BC
1A3BC
12ABC
现在假设我们有 5 个洞和 4 个弹珠。
ABCD5
ABC4D
AB3CD
A2BCD
1ABCD
这可以是任意数量的孔和任意数量的弹珠。
组合的数量由下式给出:
$combinations = factorial($number_of_holes)/(factorial($number_of_marbles)*factorial($number_of_holes-$number_of_marbles)))
(这里是阶乘函数,以备不时之需)
function factorial($number)
if ($number < 2)
return 1;
else
return ($number * factorial($number-1));
我需要但不知道如何编程,是一个函数或一个循环或其他东西,它返回一个包含孔位置的数组,给定 X 个孔和 Y 个弹珠。
第一个例子是:[[4],[3],[2],[1]]
,第二个例子是:[[4,5],[2,5],[1,5],[3,4],[2,4],[1,5],[2,3],[1,3],[1,2]]
,第三个例子是:[[5],[4],[3],[2],[1]]
。
不必按顺序返回,我只需要所有元素。
如您所见,另一种方法是互补或逆或不知道如何调用它,但解决方案是给定 Y 个孔的 X 个空闲孔的每个组合,所以,如果我有 10 个孔, 和 5 个弹珠,将有 5 个空洞,返回的数组将是 5 的每个组合,可以用 (1,2,3,4,5,6,7,8,9,10) 形成,它们是252种组合,我需要的是252种组合。
第二种方法的示例:
给定 array=[1,2,3,4]
,返回 2 和 3 的每个组合。
2 件套
[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
3 件套
[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
我需要的是执行此操作的逻辑,我正在尝试在 php 中执行此操作,但我就是不知道该怎么做。
该函数将接收数组和集合大小并返回集合数组:
function getCombinations($array,$setize)
//magic code which I can't figure out
return array(sets);
我希望这足够清楚并且有人可以帮助我,我已经卡了好几天了,但我自己似乎无法处理。
这篇文章,PHP algorithm to generate all combinations of a specific size from a single set,适用于所有可能的组合,重复元素和顺序无关紧要,它是一个很好的引导,我确实读过它,但它并没有解决我的问题,它非常不同。我需要它们而不重复元素并按照说明进行排序。
假设我的数组中已经有一组 [3,4],我不想将 [4,3] 作为另一组。
【问题讨论】:
PHP algorithm to generate all combinations of a specific size from a single set的可能重复 那篇文章是所有可能的组合,重复元素和顺序并不重要,这是一个很好的线索,我确实读过它,但它并没有解决我的问题。谢谢。 【参考方案1】:这是 PHP 中的递归解决方案:
function getCombinations($array, $setsize)
if($setsize == 0)
return [[]];
// generate combinations including the first element by generating combinations for
// the remainder of the array with one less element and prepending the first element:
$sets = getCombinations(array_slice($array, 1), $setsize - 1);
foreach ($sets as &$combo)
array_unshift($combo, $array[0]);
// generate combinations not including the first element and add them to the list:
if(count($array) > $setsize)
$sets = array_merge($sets, getCombinations(array_slice($array, 1), $setsize));
return $sets;
// test:
print_r(getCombinations([1, 2, 3, 4], 3));
算法是这样工作的:
如果 setsize 为 0,则返回单个空组合 否则,生成包含第一个元素的所有组合,方法是递归地从数组中生成所有组合,不包括 setsize - 1 个元素的第一个元素,然后将第一个元素添加到每个组合之前。 然后,如果数组大小大于 setsize(意味着包含第一个元素不是强制性的),则为列表的其余部分生成所有组合,并将它们添加到我们在第二步中生成的组合中。因此,基本上在每个步骤中,您都需要考虑一个元素是包含在组合中还是排除在组合中,并将代表两种选择的组合集合合并在一起。
【讨论】:
不客气。只是阅读大量示例算法的问题,这种想法对我来说也不是自然而然的。以上是关于给定Y个数,得到X个数的每个组合?的主要内容,如果未能解决你的问题,请参考以下文章