我不知道如何调用“排列”(甚至可能不是排列),但是利用集合中的元素是有序的这一事实,它看起来很有希望(如果不是,则有索引的顺序,所以使用索引而不是值)以便从右向左移动并将所有左与右组合结合起来。
这可以通过递归或堆栈实现,我通常更喜欢堆栈。
建议的用法(封装函数调用):
$funky = function($a, $b) {
printf("(%s) and (%s)\n", implode(',', $a), implode(',', $b));
};
$paired = function($function) {
return function(array $array) use ($function) {
...
};
};
$funkyAll = $paired($funky);
$funkyAll(range(1, 5));
使用排序的(需要更多内存)堆栈消耗策略运行此命令会给出以下输出(按列格式化):
(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (2,3,4) and (1,5)
(3) and (1,2,4,5) (3,4) and (1,2,5) (2,3,5) and (1,4)
(4) and (1,2,3,5) (3,5) and (1,2,4) (2,4,5) and (1,3)
(5) and (1,2,3,4) (4,5) and (1,2,3) (3,4,5) and (1,2)
(1,2) and (3,4,5) (1,2,3) and (4,5) (1,2,3,4) and (5)
(1,3) and (2,4,5) (1,2,4) and (3,5) (1,2,3,5) and (4)
(1,4) and (2,3,5) (1,2,5) and (3,4) (1,2,4,5) and (3)
(1,5) and (2,3,4) (1,3,4) and (2,5) (1,3,4,5) and (2)
(2,3) and (1,4,5) (1,3,5) and (2,4) (2,3,4,5) and (1)
示例性实现(作为 gist 的完整源代码)是内存优化的,并产生这个顺序(array_pop
而不是array_shift
):
(1) and (2,3,4,5) (2,4) and (1,3,5) (1,4,5) and (2,3)
(2) and (1,3,4,5) (2,5) and (1,3,4) (1,3,4) and (2,5)
(3) and (1,2,4,5) (2,4,5) and (1,3) (1,3,5) and (2,4)
(4) and (1,2,3,5) (2,3,4) and (1,5) (1,3,4,5) and (2)
(5) and (1,2,3,4) (2,3,5) and (1,4) (1,2,3) and (4,5)
(4,5) and (1,2,3) (2,3,4,5) and (1) (1,2,4) and (3,5)
(3,4) and (1,2,5) (1,2) and (3,4,5) (1,2,5) and (3,4)
(3,5) and (1,2,4) (1,3) and (2,4,5) (1,2,4,5) and (3)
(3,4,5) and (1,2) (1,4) and (2,3,5) (1,2,3,4) and (5)
(2,3) and (1,4,5) (1,5) and (2,3,4) (1,2,3,5) and (4)
执行:
$stack[] = array(array(), $array);
while (list($left, $right) = array_pop($stack)) {
$min = end($left);
foreach ($right as $value)
{
if ($value < $min) continue;
$left2 = array_merge($left, array($value));
$right2 = array_diff($right, $left2);
if (!($left2 && $count = count($right2))) continue;
$function($left2, $right2);
--$count && $stack[] = array($left2, $right2);
}
}
我希望这很有用。
另一种与数组相关的算法:用模数排序(仅供参考,在写这个时我被提醒到那个矩阵的东西)