原文是python實現的,這裡給出lua版本的實現
組合演算法
本程式的思路是開乙個陣列,其下標表示1到m個數,陣列元素的值為1表示其下標
代表的數被選中,為0則沒選中。
首先初始化,將陣列前n個元素置1,表示第乙個組合為前n個數。
然後從左到右掃瞄陣列元素值的「10」組合,找到第乙個「10」組合後將其變為
「01」組合,同時將其左邊的所有「1」全部移動到陣列的最左端。
當第乙個「1」移動到陣列的m-n的位置,即n個「1」全部移動到最右端時,就得
到了最後乙個組合。
例如求5中選3的組合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
--從長度為m的陣列中選n個元素的組合
function
comm.zuhe(atable, n)
if n > #atable then
return
{}
endlocal len = #atable
local meta ={}
--init meta data
for i=1, len do
if i <= n then
table.insert(meta, 1
)
else
table.insert(meta, 0
)
endend
local result ={}
--記錄一次組合
local tmp ={}
for i=1, len do
if meta[i] == 1
then
table.insert
(tmp, atable[i])
endend
table.insert
(result, tmp)
while
true
do--
前面連續的0
local zero_count = 0
for i=1, len-n do
if meta[i] == 0
then
zero_count = zero_count + 1
else
break
endend
--前m-n位都是0,說明處理結束
if zero_count == len-n then
break
endlocal
idx
for j=1, len-1
do--
10 交換為 01
if meta[j]==1
and meta[j+1] == 0
then
meta[j], meta[j+1] = meta[j+1
], meta[j]
idx =j
break
endend
--將idx左邊所有的1移到最左邊
local k = idx-1
local count = 0
while count <= k do
for i=k, 2, -1
doif meta[i] == 1
then
meta[i], meta[i-1] = meta[i-1
], meta[i]
endend
count = count + 1
end--
記錄一次組合
local tmp ={}
for i=1, len do
if meta[i] == 1
then
table.insert
(tmp, atable[i])
endend
table.insert
(result, tmp)
endreturn
result
end
演算法是經過優化的版本,效率還算可以,感興趣的可以自己跑一下測試!
組合演算法實現
組合 乙個集的元素的組合是乙個子集。s的乙個k 組合是s的乙個有k個元素的子集。組合具有無序性。若兩個子集的元素完全相同僅順序不同,看作同乙個組合。組合符號 這裡介紹4中常見的組合形式 1.完全組合。2.不重複完全組合。3.選擇組合。4.有重複選擇組合。1.完全組合 從n元素集s中取出所有的k個元素...
遞迴組合演算法
遞迴組合演算法 演算法思想 對於乙個長度為m的序列,要求n個數的組合。1.從索引最小的元素遍歷到第n m個元素,將遍歷到的元素定為組合中的第乙個元素 2.判斷組合中n個元素是否已滿,如果滿了,列印該組合,如果不滿重,則擷取1中選擇的元素之後的序列,復步驟一。include include using...
銀幣組合演算法分析
題目 有足夠量的2分 5分 1分硬幣,請問湊齊1元錢有多少種方法?此題乍看上去,只會覺得完全無法入手,但是按照由簡至繁的思路,我們可以先考慮極端簡單的情況,假如把問題規模縮小成 有足夠量的1分硬幣,請問湊齊1分錢有多少種方法?毫無疑問,答案是1。得到這一答案之後,我們可以略微擴大問題的規模 有足夠量...