SO,獲取可能的排列組合
從SQL我得到處理字符串數組(平面陣列)的問題 - 讓它成爲
$rgData = ['foo', 'bar', 'baz', 'bee', 'feo'];
現在,我想以獲得該陣列的配對和三元組的可能組合(並且,在一般情況下,是4個元素e tc的組合)。更具體地:我的意思是combinations在數學意義上(不重複),即那些,其計數等於
-SO爲陣列上方,這將是10,用於兩對和三元組。
我的做法
我從映射可能值開始爲可能的陣列選定的項目。我目前的解決方案是指出一個元素是否被選爲「1」,否則是「0」。對於上面的示例將是:
foo bar baz bee feo 0 0 1 1 1 -> [baz, bee, feo] 0 1 0 1 1 -> [bar, bee, feo] 0 1 1 0 1 -> [bar, baz, feo] 0 1 1 1 0 -> [bar, baz, bee] 1 0 0 1 1 -> [foo, bee, feo] 1 0 1 0 1 -> [foo, baz, feo] 1 0 1 1 0 -> [foo, baz, bee] 1 1 0 0 1 -> [foo, baz, feo] 1 1 0 1 0 -> [foo, bar, bee] 1 1 1 0 0 -> [foo, bar, baz]
而我所需要做的就是以某種方式產生所需的位集。這是我在PHP中的代碼:
function nextAssoc($sAssoc)
{
if(false !== ($iPos = strrpos($sAssoc, '01')))
{
$sAssoc[$iPos] = '1';
$sAssoc[$iPos+1] = '0';
return substr($sAssoc, 0, $iPos+2).
str_repeat('0', substr_count(substr($sAssoc, $iPos+2), '0')).
str_repeat('1', substr_count(substr($sAssoc, $iPos+2), '1'));
}
return false;
}
function getAssoc(array $rgData, $iCount=2)
{
if(count($rgData)<$iCount)
{
return null;
}
$sAssoc = str_repeat('0', count($rgData)-$iCount).str_repeat('1', $iCount);
$rgResult = [];
do
{
$rgResult[]=array_intersect_key($rgData, array_filter(str_split($sAssoc)));
}
while($sAssoc=nextAssoc($sAssoc));
return $rgResult;
}
- 我選擇將我的位存儲爲普通字符串。我對未來產生關聯算法是:
- 試圖找到「01」。如果沒有找到,那麼它是11..100..0的情況(所以它是最大的,沒有更多可以找到)。如果找到,則轉到第二步
- 轉到最右邊字符串中「01」的位置。將其切換到「10」,然後將所有比「01」位置更靠前的零移動到左側。 例如,
01110
:「01」的最右邊位置是0,所以首先我們將此「01」切換爲「10」。現在字符串是10110
。現在,轉到右邊部分(它沒有10
部分,所以它從0 + 2 =第2個符號開始),並且將全部零移動到左邊,即110
將是011
。因此,我們有10
+011
=10111
作爲下一個關聯01110
。
我發現類似的問題here - 但有OP希望組合,帶重複的,而我希望他們沒有重複。
問題
我的問題是關於兩點:
- 對於我的解決方案,可能還有另一種方式來產生下一個位爲更有效?
- 可能有更簡單的解決方案嗎?這似乎是標準問題。
的可能重複[算法返回從n個k個元素的所有組合(HTTP ://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n) – ElKamina
哇,這看起來很有趣,感謝@ElKamina –
我想我的答案是罰款,有乾淨的PHP代碼和速度之間的良好平衡。你是否忽略了它? –