我目前正在計算數據數組的唯一排列。雖然下面的代碼正在工作,但並不像我想的那樣高效。一旦我得到了6或8個項目,它變得非常慢,我開始遇到內存問題。高效計算集合中的唯一排列
下面是代碼和一個解釋
<?php
function permuteUnique($items, $count = false, $perms = [], &$return = []) {
if ($count && count($return) == $count) return $return;
if (empty($items)) {
$duplicate = false;
foreach ($return as $a) {
if ($a === $perms) {
$duplicate = true;
break;
}
}
if (!$duplicate) $return[] = $perms;
} else {
for ($i = count($items) - 1; $i >= 0; --$i) {
$newitems = $items;
$newperms = $perms;
list($tmp) = array_splice($newitems, $i, 1);
array_unshift($newperms, $tmp);
permuteUnique($newitems, $count, $newperms, $return);
}
return $return;
}
}
function factorial($n) {
$f = 1;
for ($i = 2; $i <= $n; $i++) $f *= $i;
return $f;
}
鑑於我接收預期以下輸出輸入[1, 1, 2]
array (size=3)
0 =>
array (size=3)
0 => int 1
1 => int 1
2 => int 2
1 =>
array (size=3)
0 => int 1
1 => int 2
2 => int 1
2 =>
array (size=3)
0 => int 2
1 => int 1
2 => int 1
的$count
參數,所以我可以通過獨特的排列數我期待該功能,一旦發現很多,它可以停止計算並返回數據。這被計算爲項目總數的階乘除以所有重複次數的階乘的乘積。我不確定我是否說得對,所以讓我舉個例子。
給定了[1, 2, 2, 3, 4, 4, 4, 4]
因爲有8個項目總額,其中一人被複制兩次獨特排列的計數計算 8!/(2!4!) = 840
,另一個是重複4次。
現在,如果我翻譯,爲PHP代碼...
<?php
$set = [1, 2, 2, 3, 4, 4, 4, 4];
$divisor = 1;
foreach (array_count_values($set) as $v) {
$divisor *= factorial($v);
}
$count = factorial(count($set))/$divisor;
$permutations = permuteUnique($set, $count);
這是非常緩慢的。如果我在permuteUnique
函數中拋出一個計數器,它會在找到840個唯一排列之前運行超過10萬次。
我想找到一種方法來減少這種情況,並找到最短的路徑,以獨特的排列。我感謝您能給予的任何幫助或建議。
查看C++的['std :: next_permutation'](http://en.cppreference.com/w/cpp/algorithm/next_permutation),找到或實現類似於PHP的東西。 – MvG