實現某數組的組合演算法有很多種,其中以遞迴為最多,而且網上不乏高效率的樣本,這裡只示範一種實現方式.
代碼
1 /**
2 * 遞迴組合
3 * 從 arr[1n] 中任選 num(0 < num <= n) 個數的所有組合
4 */
5 function combine(arr, num) {
6 var r = [];
7 (function f(t, a, n) {
8 if (n == 0) return r.push(t);
9 for (var i = 0, l = a.length; i <= l - n; i++) {
10 f(t.concat(a[i]), a.slice(i + 1), n - 1);
11 }
12 })([], arr, num);
13 return r;
14 }
15
16 /** 測試代碼 **/
17 combine([1,2,3,4,5,6,7,8,9], 3);
然而,事情並不是都這麼簡單,現在遇到一個新問題,我定義了一個新的數組
var arr = [[1,2,3],
[1,2,3,4,5],
[2,4,6,8],
[3,5,7,9]];
要求是從數組arr的每個元素中任意取一個值出來,組成一個長度為4(即arr.length)的組合,求有多少種組合方式.這個時候,如果想要再次利用上面的遞迴,就需要改造一下了.主要變化就是在每次傳入匿名函數的參數上,以保證每次要迴圈的數組是arr的下一個元素而不是當前元素本身.
代碼
1 function combine_ex(arr) {
2 var r = [];
3 (function f(t, a, n) {
4 if (n == 0) return r.push(t);
5 for (var i = 0; i < a[n-1].length; i++) {
6 f(t.concat(a[n-1][i]), a, n - 1);
7 }
8 })([], arr, arr.length);
9 return r;
10 }
接著就有新問題了,如果要對上面變長的二維數組,要求是從數組arr的每個元素中任意取一個值出來,組成一個長度為指定任意值的組合怎麼辦?要說辦法也就在這裡了,無非就是將前面兩種函數一起使用,先求出最長組合的集合,然後對每一個元素求指定長度的組合.
總歸,組合演算法的需求是多樣的,不管怎麼變,都能從最基本的演算法進行衍變,派生出複合的演算法出來.