這個算法有不少擴展,好比電商中購物車中的計算,滿100減20,不滿100會在熱銷商品中進行推薦填充。html
function getCombBySum(array,sum,tolerance,targetCount){ /* array: 數據源數組,必選; sum: 相加的和,必選; tolerance: 容差,若是不指定此參數,則相加的和必須等於sum參數,指定此參數能夠使結果在容差範圍內浮動,可選; targetCount: 操做數數量,若是不指定此參數,則結果包含全部可能的狀況,指定此參數能夠篩選出固定數量的數相加,假如指定爲3,那麼結果只包含三個數相加的狀況,可選; 返回值: 返回的是數組套數組結構,內層數組中的元素是操做數,外層數組中的元素是全部可能的結果; */ var util = { /* get combination from array arr: target array num: combination item length return: one array that contain combination arrays */ /*獲取全部的可能組合 若是是[1,2,3,4,5]取出3個,那麼可能性就有10種 C(5,3)= C(5,2) 公式: 全排列 P(n,m)=n!/(n-m)! 組合排列 P(n,m)=n!/m!/(n-m)! C(5,2)=5!/2!*3!=5*4*3*2*1/[(2*1)*(3*2*1)]=10 這是使用了循環加遞歸作出了組合排序 */ getCombination: function(arr, num) { // 索引數組 操做數數量 var r=[]; (function f(t,a,n){ if (n == 0) return r.push(t); for (var i=0,l=a.length; i<=l-n; i++) { f(t.concat(a[i]), a.slice(i+1), n-1); } })([],arr,num); return r; }, // 獲取數組的索引 getArrayIndex: function(array) { var i = 0, r = []; for(i = 0;i<array.length;i++){ r.push(i); } return r; } },logic = { // 對數組進行排序 // 獲取數組中比sum小的數 init: function(array,sum) { //初始化去除不可能的元素 // clone array var _array = array.concat(), r = [], i = 0; // sort by asc _array.sort(function(a,b){ return a - b; }); // 當它小於或等於總和時得到全部數字 for(i = 0;i<_array.length;i++){ if(_array[i]<=sum){ r.push(_array[i]); }else{ break; } } console.log('初始化後的數據源:', r); return r; }, // important function core: function(array,sum,arrayIndex,count,r){ var i = 0, k = 0, combArray = [], _sum = 0, _cca = [], _cache = []; if(count == _returnMark){ return; } // 獲取當前的計數總和 // 這裏排序的不是原來的數組,而是求的索引後的數組 combArray = util.getCombination(arrayIndex,count); console.log('getCombination返回的值:', combArray); for(i = 0;i<combArray.length;i++){ _cca = combArray[i]; _sum = 0; _cache = []; // calculate the sum from combination for(k = 0;k<_cca.length;k++){ _sum += array[_cca[k]]; _cache.push(array[_cca[k]]); } if(Math.abs(_sum-sum) <= _tolerance){ r.push(_cache); } } logic.core(array,sum,arrayIndex,count-1,r); } }, r = [], _array = [], _targetCount = 0, _tolerance = 0, _returnMark = 0; // check data _targetCount = targetCount || _targetCount; _tolerance = tolerance || _tolerance; _array = logic.init(array,sum); if(_targetCount){ _returnMark = _targetCount-1; } console.log('_targetCount的值:', _targetCount); console.log('_returnMark的值:', _returnMark); logic.core(_array,sum,util.getArrayIndex(_array),(_targetCount || _array.length),r); return r; } var res1 = getCombBySum([1, 2, 3, 4, 5], 6, null, 2); // var res2 = getCombBySum([1, 2, 3, 4, 5, 9, 7, 10, 8], 9, null, null); console.log(res1); // console.log(res2);
更多其它內容請查看git