如果您一次只需要一個元素,則可以通過單獨生成每個元素來節省內存。
如果我們想要生成您所設定的預期產出的隨機字符串,我們可以用這個算法:
Given a set of characters S, and a desired output length K:
While the output has less than K characters:
Pick a random number P between 1 and |S|.
Append the P'th character to the output.
Remove the P'th character from S.
其中|S|
是元素的S.
目前一些
我們實際上可以將這個選擇序列編碼成一個整數。要做到這一點的方法之一是改變算法,例如:
Given a set of characters S, and a desired output length K:
Let I = 0.
While the output has less than K characters:
I = I * (|S| + 1).
Pick a random number P between 1 and the number of elements in S.
I = I + P.
Append the P'th character to the output.
Remove the P'th character from S.
運行該算法後,該值將I
唯一編碼的選擇這個特殊的序列。它基本上將其編碼爲mixed-radix數字;一個數字使用基數N,下一個使用N-1,依此類推,直到最後一個數字爲基數N-K + 1(N爲輸入中的字母數)。
當然,我們還可以再解碼這一點,在PHP中,這將是這樣的:
// Returns the total number of $count-length strings generatable from $letters.
function getPermCount($letters, $count)
{
$result = 1;
// k characters from a set of n has n!/(n-k)! possible combinations
for($i = strlen($letters) - $count + 1; $i <= strlen($letters); $i++) {
$result *= $i;
}
return $result;
}
// Decodes $index to a $count-length string from $letters, no repeat chars.
function getPerm($letters, $count, $index)
{
$result = '';
for($i = 0; $i < $count; $i++)
{
$pos = $index % strlen($letters);
$result .= $letters[$pos];
$index = ($index-$pos)/strlen($letters);
$letters = substr($letters, 0, $pos) . substr($letters, $pos+1);
}
return $result;
}
(請注意,爲簡單起見,這個特殊的解碼算法不完全對應的編碼算法我先前所述,但保持給定$index
映射到唯一結果的期望屬性。)
若要使用此代碼,你會做這樣的事情:
$letters = 'abcd';
echo '2 letters from 4:<br>';
for($i = 0; $i < getPermCount($letters, 2); $i++)
echo getPerm($letters, 2, $i).'<br>';
echo '<br>3 letters from 4:<br>';
for($i = 0; $i < getPermCount($letters, 3); $i++)
echo getPerm($letters, 3, $i).'<br>';
?>
他將如何節省內存?他需要「所有可能的排列或組合」。算法的差異不會使結果排列變小。 – BeRocket
@UAWDT:當你處理排列問題時,你通常只需要遍歷它們並單獨處理它們。您不需要將它們全部存儲在一個大數組中以便實現這一點 - 您可以根據需要生成每個元素,並在完成後將其丟棄。換句話說,它是'$ perms = getPerms();之間的區別。 foreach($ perms as perm)'和'for($ i = 0; $ i