计算所有加起来为数字的组合

时间:2018-08-03 15:21:12

标签: javascript calculator

我有一个脚本,可以为我提供一组数字的所有可能组合,这些数字加起来就是一个数字。但是我不希望有最小或最大数字,但是我希望能够输入所需的数字。因此,我的目标可能是“ 3”,并且包含数字1和2的集合。如您所见,我还希望能够具有所有可能的顺序,并且每个数字可以多次使用。在这种情况下,结果将是:1+1+1, 2+1, 1+2。我还希望显示结果数。

<!DOCTYPE html>
<html>

<head>
  <title>Sum</title>
</head>

<body>

  <style>
    .table {
      display: table;
      table-layout: fixed;
      width: 100%;
    }
    
    .table-row {
      display: table-row;
    }
    
    .cell {
      display: table-cell;
    }
  </style>

  <div class="table">
    <div class="table-row">
      <div class="cell">Target:</div>
      <div class="cell">
        <input id="target" type="text" value=15>
      </div>
      <div class="cell">n:</div>
      <div class="cell">
        <input id="n" type="text" value=3>
      </div>
    </div>
    <div class="table-row">
      <div class="cell">Min:</div>
      <div class="cell">
        <input id="min" type="text" value=1>
      </div>
      <div class="cell">Max:</div>
      <div class="cell">
        <input id="max" type="text" value=12>
      </div>
    </div>
  </div>
  <input id="submit" type="button" value="submit" />
  <div id="output" />

  <script>
    function getCombos(target, min, max, n) {
      var arrs = [];
      if (n === 1 && target <= max) {
        arrs.push([target]);
      } else {
        for (var i = min; i < target / n && i <= max; i++) {
          var nextTarget = target - i;
          var nextMin = i + 1;
          var arrays = getCombos(nextTarget, nextMin, max, n - 1);
          for (var j = 0; j < arrays.length; j++) {
            var array = arrays[j];
            array.splice(0, 0, i);
            arrs.push(array);
          }
        }
      }
      return arrs;
    }

    document.getElementById("submit").onclick = function() {
      var target = document.getElementById("target").value;
      var min = document.getElementById("min").value;
      var max = document.getElementById("max").value;
      var n = document.getElementById("n").value;
      var result = getCombos(+target, +min, +max, +n);
      document.getElementById("output").innerHTML = result.join("<br/>");
    };
  </script>
</body>

</html>

1 个答案:

答案 0 :(得分:1)

正如评论中所指出的,这是subset-sum problem的一个版本(但不是求和为0,而是求和一些期望的数字)。

Wikipedia页面确实给出了O(2 ^ (n/2)),但是由于您的输入看起来很小,因此我将仅实现O(2 ^ N * N)蛮力算法来解决此问题。

function get_summing_subsets(set_arr, target){
     let finish = [];
     let working = [[]];
     while (working.length){
         let next_work = [];
         for (let i = 0; i < working.length; i++){
             for (let j = 0; j < set_arr.length; j++){
                 let subset = working[i].concat([set_arr[j]]);
                 let sum = subset.reduce((a,b) => a + b, 0);
                 if (sum <= target){
                     (sum == target ? finish : next_work).push(subset);
                 }
             }
         }
         working = next_work
     }
     return finish;
}

效果很好:

//your example
get_summing_subsets([1,2], 3)
[[1,2],[2,1],[1,1,1]]
//another
get_summing_subsets([1,2,3], 4)
[[1,3],[2,2],[3,1],[1,1,2],[1,2,1],[2,1,1],[1,1,1,1]]