我不知道“排列”是如何被调用的(它甚至可能不是排列),但它看起来很有希望利用集合中的元素是有序的这一事实(如果不是,则有索引,所以使用索引而不是值),以便从右向左移动并将所有左与右组合结合起来。
这可以通过递归或堆栈实现,我通常更喜欢堆栈。
建议的用法(封装函数调用):
$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)
示例实现 (full source-code as 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);
}
}
我希望这是有用的。
另一个与数组相关的算法:Sorting with a modulus(仅供参考,写这个的时候我想起了那个矩阵的东西)