高效率的排列組合算法--《編程珠磯》--Lua實現
原文是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 {} end local 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) end end local result = {} -- 記錄一次組合 local tmp = {} for i=1, len do if meta[i] == 1 then table.insert(tmp, atable[i]) end end 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 end end -- 前m-n位都是0,說明處理結束 if zero_count == len-n then break end local 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 end end -- 將idx左邊所有的1移到最左邊 local k = idx-1 local count = 0 while count <= k do for i=k, 2, -1 do if meta[i] == 1 then meta[i], meta[i-1] = meta[i-1], meta[i] end end count = count + 1 end -- 記錄一次組合 local tmp = {} for i=1, len do if meta[i] == 1 then table.insert(tmp, atable[i]) end end table.insert(result, tmp) end return result end
算法是經過優化的版本,效率還算可以,感興趣的可以自己跑一下測試!