function _combine($numbers, $length)
{
$combinations = array();
$stack = array();
// every combinations can be ordered
sort($numbers);
// startup
array_push($stack, array(
'store' => array(),
'options' => $numbers,
));
while (true) {
// pop a item
$item = array_pop($stack);
// end of stack
if (!$item) {
break;
}
// valid store
if ($length <= count($item['store'])) {
$combinations[] = $item['store'];
continue;
}
// bypass when options are not enough
if (count($item['store']) + count($item['options']) < $length) {
continue;
}
foreach ($item['options'] as $index => $n) {
$newStore = $item['store'];
$newStore[] = $n;
// every combine can be ordered
// so accept only options which is greater than store numbers
$newOptions = array_slice($item['options'], $index + 1);
// push new items
array_push($stack, array(
'store' => $newStore,
'options' => $newOptions,
));
}
}
return $combinations;
}
function combinations(array $items, int $numToChoose, array &$results, $comb = []): void {
if (count($items) < $numToChoose) {
throw new \Exception("Asked to choose $numToChoose items from an array of length ". count($items));
}
// if nothing left to choose, we have a complete combination
if ($numToChoose === 0) {
$results[] = $comb;
return;
}
// if we have to choose everything at this point, then we know what to do
if (count($items) == $numToChoose) {
$results[] = $comb + $items;
return;
}
// The recursive cases: either use the first element or not and find combinations of the rest
$val = reset($items);
$key = key($items);
unset($items[$key]);
// not using it
combinations($items, $numToChoose, $results, $comb);
// using it
$comb[$key] = $val;
combinations($items, $numToChoose - 1, $results, $comb);
}
// Do a test run
$combs = [];
combinations([1=>1, 2=>2, 3=>3], 2, $combs);
var_dump($perms);
8条答案
按热度按时间6yt4nkrj1#
您可以使用http://stereofrog.com/blok/on/070910中的解决方案。
如果链接中断,这是密码...
12345 12346 12347 12356 12357 12367 12456 12457 12467 12567 13456 13457 13567 14567 23456 23457 23467 23567 24567 34567
rdrgkggo2#
输出
eqoofvh93#
PEAR存储库中的
Math_Combinatorics
完全符合您的要求:返回给定集合和子集大小的所有组合和排列的包,没有重复。保留关联数组。
kupeojn64#
另一个基于堆栈的解决方案。它速度很快,但占用大量内存。
希望这能帮上忙。
详细内容:
muk1a3rh5#
改进了此answer,使其也可以使用关联数组:
例如:
结果:
它仍然适用于非关联数组:
结果:
kqqjbcuj6#
优化组合算法速度和内存的新方案
思维模式:生成K个数组的组合。新的解决方案将使用K个“for”语句。一个“for”一个数字。例如:$K = 5表示使用了5个“for”语句
以及生成将由eval()函数执行的真实的代码的代码细节
如何合并K个数组
insrf1ej7#
我发现这里的其他答案令人困惑或过于复杂,所以我写了自己的答案。我认为这是一个递归方法的简单解决方案。基本思想是你遍历你的数组,并为每一项确定它是否在组合中(实际上,你不能决定,你递归地尝试两种方式)。你为第一项做这个选择,然后将它与数组其余部分递归生成的组合组合在一起。此解决方案使用数组的每个组合作为子数组填充结果数组。它按顺序使用项并保留关联,包括与数字键的关联。
这将产生以下输出:
bakd9h0s8#
我需要一个包含子集的组合函数,所以我采用了
@Nguyen Van Vinh
的答案,并根据需要进行了修改。如果将
[1,2,3,4]
传递给函数,它将返回每个唯一组合和子集,排序如下:函数如下: