下一个字典顺序 n k 的排列
Next permutation in lexicographic order n k
我想编写 returns 下一个字典顺序排列 n 选择 k 的函数。
到目前为止我发现了以下算法
class Permutation
{
public function swap(& $a, $first, $second)
{
$tmp = $a[$first];
$a[$first] = $a[$second];
$a[$second] = $tmp;
}
function nextPermutation(& $a, $n, $k)
{
do {
$first = $n - 2;
while ($first != -1 && $a[$first] >= $a[$first + 1]) $first--;
if ($first == -1)
return false;
$second = $n - 1;
while ($a[$first] >= $a[$second]) $second--;
$this->swap($a, $first, $second);
$left = $first + 1;
$right = $n - 1;
while ($left < $right) {
$this->swap($a, $left++, $right--);
}
} while ($first > $k - 1);
return true;
}
public function run()
{
$n=10;
$k=4;
$a = array_merge(range(ord(0), ord(9)), range(ord('A'), ord('Z')), range(ord('a'), ord('z')));
$i = 0;
while ($this->nextPermutation($a, $n, $k)) {
$i++;
echo($i . ") ");
for ($j = 0; $j < $k; $j++) {
echo $a[$j] . " ";
}
echo("\n");
}
}
}
但它只适用于 n 最多 13,然后变得很慢。
我需要让它适用于 n=62 和 k=6。可以吗?
该组合对象在英文组合学中没有具体名称,在俄文和法文组合学术语中称为"arrangements" A(n,k)
有 44 261 653 680 个排列 A(62,6)
- 因此它们的生成和输出(~500 GB)花费的时间太长。在像 C/C++/Delphi 这样的编译语言中生成(没有输出)可能需要大约几个小时(粗略估计每秒 10^6-10^7 个结果),但这个过程应该更慢在 PHP(解释语言)中。
您的代码使用算法进行常规排列,根据需要的 n!/(n-k)!
排列生成 n!
结果。
用于生成安排的简单递归 Python 代码。对于 n=25,k=5,工作约 3 秒。不是最优的,会在书上查一下。
n = 4
k = 2
ar = [0] * k
used = set()
def genArr(idx):
for i in range(n):
if not i in used:
used.add(i)
ar[idx] = i
if idx == k - 1:
print(ar) #comment for large n
else:
genArr(idx + 1)
used.remove(i)
genArr(0)
print('OK')
[0, 1, 2]
[0, 1, 3]
[0, 2, 1]
[0, 2, 3]
......
[2, 3, 1]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]
我想编写 returns 下一个字典顺序排列 n 选择 k 的函数。
到目前为止我发现了以下算法
class Permutation
{
public function swap(& $a, $first, $second)
{
$tmp = $a[$first];
$a[$first] = $a[$second];
$a[$second] = $tmp;
}
function nextPermutation(& $a, $n, $k)
{
do {
$first = $n - 2;
while ($first != -1 && $a[$first] >= $a[$first + 1]) $first--;
if ($first == -1)
return false;
$second = $n - 1;
while ($a[$first] >= $a[$second]) $second--;
$this->swap($a, $first, $second);
$left = $first + 1;
$right = $n - 1;
while ($left < $right) {
$this->swap($a, $left++, $right--);
}
} while ($first > $k - 1);
return true;
}
public function run()
{
$n=10;
$k=4;
$a = array_merge(range(ord(0), ord(9)), range(ord('A'), ord('Z')), range(ord('a'), ord('z')));
$i = 0;
while ($this->nextPermutation($a, $n, $k)) {
$i++;
echo($i . ") ");
for ($j = 0; $j < $k; $j++) {
echo $a[$j] . " ";
}
echo("\n");
}
}
}
但它只适用于 n 最多 13,然后变得很慢。 我需要让它适用于 n=62 和 k=6。可以吗?
该组合对象在英文组合学中没有具体名称,在俄文和法文组合学术语中称为"arrangements" A(n,k)
有 44 261 653 680 个排列 A(62,6)
- 因此它们的生成和输出(~500 GB)花费的时间太长。在像 C/C++/Delphi 这样的编译语言中生成(没有输出)可能需要大约几个小时(粗略估计每秒 10^6-10^7 个结果),但这个过程应该更慢在 PHP(解释语言)中。
您的代码使用算法进行常规排列,根据需要的 n!/(n-k)!
排列生成 n!
结果。
用于生成安排的简单递归 Python 代码。对于 n=25,k=5,工作约 3 秒。不是最优的,会在书上查一下。
n = 4
k = 2
ar = [0] * k
used = set()
def genArr(idx):
for i in range(n):
if not i in used:
used.add(i)
ar[idx] = i
if idx == k - 1:
print(ar) #comment for large n
else:
genArr(idx + 1)
used.remove(i)
genArr(0)
print('OK')
[0, 1, 2]
[0, 1, 3]
[0, 2, 1]
[0, 2, 3]
......
[2, 3, 1]
[3, 0, 1]
[3, 0, 2]
[3, 1, 0]
[3, 1, 2]
[3, 2, 0]
[3, 2, 1]