排列 - 所有可能的数字集

2022-08-30 12:18:45

我有数字,从0到8。我希望结果是,这些数字的所有可能的集合,每个集合都应该使用所有数字,每个数字在一个集合中只能出现一次。

我希望看到PHP中可以打印出结果的解决方案。或者,至少,我想要一些关于组合学理论的茶点,因为我早就忘记了它。计算有多少个排列的公式是什么?

示例集:

  • 0-1-2-3-4-5-6-7-8
  • 0-1-2-3-4-5-6-8-7
  • 0-1-2-3-4-5-8-6-7
  • 0-1-2-3-4-8-5-6-7
  • 0-1-2-3-8-4-5-6-7
  • 0-1-2-8-3-4-5-6-7
  • 等等...

答案 1

您正在寻找排列公式:

nPk = n!/(n-k)!

在你的情况下,你有9个条目,你想选择所有这些条目,那就是9P9 = 9!= 362880

您可以在O'Reilly的“PHP Cookbook”的配方4.26中找到一个PHP算法进行排列。

pc_permute(array(0, 1, 2, 3, 4, 5, 7, 8));

抄自O'Reilly:

function pc_permute($items, $perms = array( )) {
    if (empty($items)) { 
        print join(' ', $perms) . "\n";
    }  else {
        for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
             list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             pc_permute($newitems, $newperms);
         }
    }
}

答案 2

从 PHP 5.5 开始,您可以使用生成器。生成器节省大量内存并且速度更快(与pc_permute()相比,一半以上)。因此,如果您有机会安装PHP 5.5,那么您肯定需要Generators。这个截图是从Python移植过来的:https://stackoverflow.com/a/104436/3745311

function permutations(array $elements)
{
    if (count($elements) <= 1) {
        yield $elements;
    } else {
        foreach (permutations(array_slice($elements, 1)) as $permutation) {
            foreach (range(0, count($elements) - 1) as $i) {
                yield array_merge(
                    array_slice($permutation, 0, $i),
                    [$elements[0]],
                    array_slice($permutation, $i)
                );
            }
        }
    }
}

示例用法:

$list = ['a', 'b', 'c'];

foreach (permutations($list) as $permutation) {
    echo implode(',', $permutation) . PHP_EOL;
}

输出:

a,b,c
b,a,c
b,c,a
a,c,b 
c,a,b
c,b,a

推荐