You may have several solutions. A dynamic programming approach could effectively solve this problem,
function getCombos(a,t){ var h = {}, len = a.length, n = 0; for (var i = 0; i < len; i++){ n = a[i]; h[n] ? h[n].push([n]) : h[n] = [[n]]; for(var j = a[0]; j <= tn; j++){ h[j] && (h[j+n] = h[j+n] ? h[j+n].concat(h[j].map(s => s.concat(n))) : h[j].map(s => s.concat(n))); } } return h[t] || []; } var arr = [1,2,5,10,50], target = 28, result = []; console.time("combos"); result = getCombos(arr,target); console.timeEnd("combos"); console.log(`${result.length} solutions found`); console.log(JSON.stringify(result));
Then you can choose the shortest among the result set. However, computing according to a maxlen will couse will save us from calculating redundant results that will be filtered out later. Thus, the following code only works until reaching maxlen .
function getCombos(a,t,l){ var h = {}, len = a.length, n = 0; for (var i = 0; i < len; i++){ n = a[i]; h[n] ? h[n].push([n]) : h[n] = [[n]]; for(var j = a[0]; j <= tn; j++){ h[j] && (h[j+n] = h[j+n] ? h[j+n].concat(h[j].reduce((r,s) => s.length < l ? (r.push(s.concat(n)),r) : r, [])) : h[j].reduce((r,s) => s.length < l ? (r.push(s.concat(n)),r) : r, [])); } } return h[t] || []; } var arr = [1,2,5,10,50], target = 28, maxlen = 5, result = []; console.time("combos"); result = getCombos(arr,target,maxlen); console.timeEnd("combos"); console.log(result.length) console.log(JSON.stringify(result));
I believe that wise performance cannot be easily beaten. Only 0.17 ms is required to achieve the result [[1,2,5,10,10]] .
source share