使用javascript输出数字数组的每个组合

时间:2010-10-30 23:12:36

标签: javascript combinations

我在数组中有几个数字

var numArr = [1, 3, 5, 9];

我想循环遍历该数组并将每个唯一的3个数字组合相乘,如下所示:

1 * 3 * 5 = 
1 * 3 * 9 = 
1 * 5 * 9 = 
3 * 5 * 9 =

然后返回所有计算的数组

var ansArr = [15,27,45,135];

任何人都有优雅的解决方案?提前谢谢。

6 个答案:

答案 0 :(得分:12)

用于生成组合的通用算法如下:

function combinations(numArr, choose, callback) {
    var n = numArr.length;
    var c = [];
    var inner = function(start, choose_) {
        if (choose_ == 0) {
            callback(c);
        } else {
            for (var i = start; i <= n - choose_; ++i) {
                c.push(numArr[i]);
                inner(i + 1, choose_ - 1);
                c.pop();
            }
        }
    }
    inner(0, choose);
}

在你的情况下,你可以这样称呼它:

function product(arr) {
    p = 1;
    for (var i in arr) {
        p *= arr[i];
    }
    return p;
}

var ansArr = [];

combinations(
    [1, 3, 5, 7, 9, 11], 3,
    function output(arr) {
        ansArr.push(product(arr));
    });

document.write(ansArr);

...对于给定的输入,产生这个:

15,21,27,33,35,45,55,63,77,99,105,135,165,189,231,297,315,385,495,693

答案 1 :(得分:2)

我认为这应该有效:

var a = [1, 3, 5, 9];
var l = a.length;
var r = [];
for (var i = 0; i < l; ++i) {
  for (var j = i + 1; j < l; ++j) {
    for (var k = j + 1; k < l; ++k) {
      r.push(a[i] * a[j] * a[k]);
    }
  }
}

修改

仅仅为了我自己的启发,我找到了一个使用循环而不是递归的通用解决方案。显而易见的缺点是它更长,因此加载或读取速度更慢。另一方面(至少在我的机器上的Firefox上)它的运行速度是递归版本的两倍。但是,我只推荐它,如果你找到大型组合的组合,或在同一页面上多次找到组合。无论如何,如果有人感兴趣,这就是我想出来的。

function combos(superset, size) {
  var result = [];
  if (superset.length < size) {return result;}
  var done = false;
  var current_combo, distance_back, new_last_index;
  var indexes = [];
  var indexes_last = size - 1;
  var superset_last = superset.length - 1;

  // initialize indexes to start with leftmost combo
  for (var i = 0; i < size; ++i) {
    indexes[i] = i;
  }

  while (!done) {
    current_combo = [];
    for (i = 0; i < size; ++i) {
      current_combo.push(superset[indexes[i]]);
    }
    result.push(current_combo);
    if (indexes[indexes_last] == superset_last) {
      done = true;
      for (i = indexes_last - 1; i > -1 ; --i) {
        distance_back = indexes_last - i;
        new_last_index = indexes[indexes_last - distance_back] + distance_back + 1;
        if (new_last_index <= superset_last) {
          indexes[indexes_last] = new_last_index;
          done = false;
          break;
        }
      }
      if (!done) {
        ++indexes[indexes_last - distance_back];
        --distance_back;
        for (; distance_back; --distance_back) {
          indexes[indexes_last - distance_back] = indexes[indexes_last - distance_back - 1] + 1;
        }
      }
    }
    else {++indexes[indexes_last]}
  }
  return result;
}

function products(sets) {
  var result = [];
  var len = sets.length;
  var product;
  for (var i = 0; i < len; ++i) {
    product = 1;
    inner_len = sets[i].length;
    for (var j = 0; j < inner_len; ++j) {
      product *= sets[i][j];
    }
    result.push(product);
  }
  return result;
}

console.log(products(combos([1, 3, 5, 7, 9, 11], 3)));

答案 2 :(得分:0)

当需要在n个数中选择k个数时,执行此操作的递归函数。没有测试过。找出是否有任何错误并纠正它: - )

var result = [];

foo(arr, 0, 1, k, n); // initial call

function foo(arr, s, mul, k, n) {
    if (k == 1) {
        result.push(mul);
        return;
    }

    var i;
    for (i=s; i<=n-k; i++) {
        foo(arr, i+1, mul*arr[i], k-1, n-i-1);
    }
}

这是一个递归函数。

  1. 第一个参数是数组arr

  2. 第二个参数是整数s。每次调用都会计算从索引s开始的部分数组的值。递归地我增加s,因此每个调用的数组递归地变小。

  3. 第三个参数是递归计算并在递归调用中传递的值。当k变为1时,它将添加到结果数组中。

  4. k所需组合的大小。它递归递减,当变为1时,输出附加在结果数组中。

  5. n是数组arr的大小。实际上n = arr.length

答案 3 :(得分:0)

var create3Combi = function(array) {
    var result = [];
    array.map(function(item1, index1) {
        array.map(function(item2, index2) {
            for (var i = index2 + 1; i < array.length; i++) {
                var item3 = array[i];
                if (item1 === item2 || item1 === item3 || item2 === item3 || index2 < index1) {
                    continue;
                }
                result.push([item1, item2, item3]);
            }
        });
    });

    return result;
};

var multiplyCombi = function(array) {
    var multiply = function(a, b){
        return a * b;
    };

    var result = array.map(function(item, index) {
        return item.reduce(multiply);
    });

    return result;
}

var numArr = [1, 3, 5, 9];

//  create unique 3 number combination
var combi = create3Combi(numArr); //[[1,3,5],[1,3,9],[1,5,9],[3,5,9]]

// multiply every combination
var multiplyResult = multiplyCombi(combi); //[15,27,45,135];

答案 4 :(得分:0)

https://github.com/dankogai/js-combinatorics

找到了这个图书馆。经测试可以正常工作。以下是图书馆文件的内容:

var Combinatorics = require('js-combinatorics');
var cmb = Combinatorics.combination(['a','b','c','d'], 2);
while(a = cmb.next()) console.log(a);
//  ["a", "b"]
//  ["a", "c"]
//  ["a", "d"]
//  ["b", "c"]
//  ["b", "d"]
//  ["c", "d"]

答案 5 :(得分:-1)

使用节点,您可以使用库轻松地完成此操作。首先使用npm:

安装bit-twiddle
npm install bit-twiddle

然后你可以在你的代码中使用它:

//Assume n is the size of the set and k is the size of the combination
var nextCombination = require("bit-twiddle").nextCombination
for(var x=(1<<(k+1))-1; x<1<<n; x=nextCombination(x)) {
   console.log(x.toString(2))
}

变量x是一个位向量,如果组合中包含i元素,则设置位i