Javascript 返回数组中总和小于或等于n的所有可能的数字组合

Javascript 返回数组中总和小于或等于n的所有可能的数字组合,javascript,combinations,permutation,Javascript,Combinations,Permutation,也许我遗漏了一些正确的答案,但你明白了。真想知道如何解决这个问题 试试这个: var a = [1,3,6,10,-1]; function combinations(array, n) { } combinations(a, 9) // should return... [[1], [3], [6], [-1], [1,3], [1,6], [1,-1], [3,6], [3,-1], [6, -1], [10, -1], [1,3,-1], [3,6,-1], [1,6,-1], [1,3

也许我遗漏了一些正确的答案,但你明白了。真想知道如何解决这个问题

试试这个:

var a = [1,3,6,10,-1];
function combinations(array, n) {
}

combinations(a, 9) // should return...
[[1], [3], [6], [-1], [1,3], [1,6], [1,-1], [3,6], [3,-1], [6, -1], [10, -1], [1,3,-1], [3,6,-1], [1,6,-1], [1,3,6,-1]]

编辑:在到期时给予信用。。借用了这一逻辑的大部分

强力O(N*2N)解,其中
N=a.length<31

这使用索引
i
作为位字段,以
过滤
每个迭代中
a
的元素到子列表中

[[1], [3], [6], [-1], [1, 3], [1, 6], [1, -1], [3, 6], [3, -1], [6, -1], [10, -1], [1, 3, -1], [1, 6, -1], [3, 6, -1], [1, 3, 6, -1]]
var a=[1,3,6,10,-1];
函数组合(数组,n){
var列表=[],M=1k&1});

如果(sublist.reduce(function(p,c){return p+c},0),我想说这里的问题是取数组的幂集,并将其过滤到只有和大于某个数的元素

一个集合的幂集是该集合的所有子集的集合。(如果快五倍,你就会成为数学家)

例如,
[1]
的幂集是
[[],[1]]
[1,2]
的幂集是
[],[1],[2],[1,2]]

    var lastElement = arr.pop();
首先,我将定义一个
powerSet
函数,如下所示:

var a = [1,3,6,10,-1];

function combinations(array, n) {
    var lists = [], M = 1<<array.length;
    for( var i = 1 ; i < M ; ++i ) {
        var sublist = array.filter(function(c,k){return i>>k & 1});
        if( sublist.reduce(function(p,c){return p+c},0) <= n )
            lists.push(sublist);
    }
    return lists;
}

console.log(JSON.stringify(combinations(a,9)));
如果传入至少包含一个元素的集合,则
powerSet
函数将从删除最后一个元素开始。例如,如果在
[1,2]
上调用
powerSet
,变量
lastElement
将设置为
2
,而
arr
将设置为
[1]

var powerSet = function (arr) {

    if(arr.length === 0) {
        return [[]];
    }
然后,
powerSet
函数递归调用自身以获取列表中“其余”部分的电源集。如果您传入了
[1,2]
,则
restpowset
将被分配给
powerSet([1])
,即
[[],[1]

    var lastElement = arr.pop();
我们定义了一个变量,它将保存传入内容的幂集,这里
[1,2]

    var restPowerset = powerSet(arr);
我们在
restpowset
中循环遍历每个集合

    var powerset = [];
如果将元素
2
添加到
[1]
的任何子集,则该元素也是
[1,2]
的子集,因此我们将其添加到列表中。
[2]
[1,2]
都是
[1,2]
的子集

    for(var i = 0; i < restPowerset.length; i++) {

        var set = restPowerset[i];
        powerset.push(set);
仅此而已。此时,变量
powerset
[[],[2],[1],[1,2]]]
。返回它

        set = set.slice(); // copy the array
        set.push(lastElement); // add the element
        powerset.push(set);

不玩看起来很有趣,以下是我所拥有的

Javascript

    }

    return powerset;
};
/**
* Get an array of all the possible combinations
* of x items.  Combinations are represented as binary.
* @param {Number} x - example 2
* @return {String[]} - example ['00', '01', '10', '11']
*/
function getCombinationsOfXItems(x) {

  var allOn = '',
    numCombos = 0,
    i = 0,
    combos = [];

  // find upper limit
  while (allOn.length < x) {
    allOn += 1;
  }

  // number of possible combinations
  numCombos = parseInt(allOn, 2) + 1;

  // generate the combos
  while(i < numCombos) {
    combos.push(pad(toBase2(i++), allOn.length));
  }

  return combos;
}

/**
* Pad a string with leading zeros.
* @param {String} x - example '100'
* @param {Number} length - example 6
* @return {String} - example '000100'
*/
function pad(x, length) {
  while (x.length < length) {
    x = 0 + x;
  }

  return x;
}

/**
* Get a number as a binary string.
* @param {Number} x - example 3
* @return {String} - example '11'
*/
function toBase2(x) {
  return x.toString(2);
}

/**
* Given an array and a map of its items as a binary string,
* return the items identified by 1.
* @param {Array} arr - example [1,2,3]
* @param {String} binary - example '101'
* @return {Array} - example [1,3]
*/
function pluckFromArrayByBinary(arr, binary) {
  var  plucked = [],
    i = 0,
    max = binary.length;

  for (; i < max; i++) {
    if (binary[i] === '1') {
      plucked.push(arr[i]);
    } 
  }

  return plucked;
}

/**
* Given an array, return a multi-dimensional
* array of all the combinations of its items.
* @param {Array} - example [1, 2];
* @return {Array[]} - [ [1], [1, 2], [2] ]
*/
function getCombosOfArrayItems(arr) {
  var comboMaps = getCombinationsOfXItems(arr.length),
    combos = [];

  // remove the "all off" combo (ex: '00000')
  comboMaps.shift();

  for (var i = 0; i < comboMaps.length; i++) {
    combos.push(pluckFromArrayByBinary(arr, comboMaps[i]));
  }

  return combos;
}

/**
* Return all possible combinations of numbers in an
* array whose sum is less than or equal to n
* @param {Number[]} arr
* @param {Number} x
* return {Number[]} - stringified for readability
*/
function combinations(arr, x) {
  var combos = getCombosOfArrayItems(arr),
    i = 0,
    max = combos.length,
    combo;

  for (; i < max; i++) {
    if (sumArray(combos[i]) > x) {
      combos.splice(i, 1);
      i--;
      max--;
    }
  }

  return JSON.stringify(combos);
}

/**
* Return the sum of an array of numbers.
* @param {Number[]} arr
* @return {Number}
*/
function sumArray(arr) {
  var sum = 0,
    i = 0,
    max = arr.length;

  for (; i < max; i++) {
    sum += arr[i];
  }

  return sum;
}

console.log(combinations([1, 3, 6, 10, -1], 9));

尽管@jcarcenter solutions给出了一个模棱两可的定义,但这其中还是有很多

在现代浏览器上,您可以使用
for
intead of
从这个解决方案中榨取更多,因为它们对
for
进行了高度优化。通过索引分配而不是
推送
也可以提高性能


如果我觉得无聊的话,最好扩展性能测试以包含更多的测试集。

类似于Matt的答案,但使用Array.filter()和Array.reduce()来填充一个打孔。在本例中,
mask
变量从1增加到32-1(因为数组长度为5,
count
=1i)&1==1} var sum=函数(a,b){返回a+b} 用于(掩码=1;掩码<计数;++掩码){ 置换.推(数组.过滤器(不可测)) }
返回置换。filter(函数(p){return p.reduce(sum)这里的简洁性非常神秘。一些描述性函数如何

该方法使用二进制创建所有可能组合的映射。然后映射用于从数组中提取项目。提取的项目被求和,仅此而已

产生的
组合([1,3,6,10,-1],9)
的结果是:
[1]、[10,-1]、[6]、[6,-1]、[3]、[3,-1]、[3,6]、[3,6,-1]、[1,6]、[1,6]、[1,6,-1]、[1,3]、[1,3,6,-1]

    var lastElement = arr.pop();

/**
*获取所有可能组合的数组
*共x项。组合表示为二进制。
*@param{Number}x-示例2
*@return{String[]}-示例['00','01','10','11']
*/
函数getCombinationsOfXItems(x){
变量allOn=“”,
numCombos=0,
i=0,
组合=[];
//求上限
while(allOn.length        set = set.slice(); // copy the array
        set.push(lastElement); // add the element
        powerset.push(set);
    }

    return powerset;
};
function kCombs(set, k) {
    var setLength = set.length,
        combs = [],
        i = 0,
        tailLength,
        head,
        tail,
        j,
        t,
        u;

    if (k > 0 && k <= setLength) {
        if (k === setLength) {
            combs.push(set);
        } else if (k === 1) {
            while (i < setLength) {
                combs.push([set[i]]);
                i += 1;
            }
        } else {
            u = k - 1;
            setLength = setLength - k + 1;
            while (i < setLength) {
                t = i + 1;
                head = set.slice(i, t);
                tail = kCombs(set.slice(t), u);
                j = 0;
                tailLength = tail.length;
                while (j < tailLength) {
                    combs.push(head.concat(tail[j]));
                    j += 1;
                }

                i = t;
            }
        }
    }

    return combs;
}

function combinations(array, n) {
    var arrayLength = array.length,
        combs = [],
        combsLength,
        results = [],
        temp = 0,
        current,
        currentLength,
        i,
        j,
        k = 1;

    while (k <= arrayLength) {
        i = 0;
        current = kCombs(array, k);
        currentLength = current.length;
        while (i < currentLength) {
            combs.push(current[i]);
            i += 1;
        }

        k += 1;
    }

    i = 0;
    combsLength = combs.length;
    while (i < combsLength) {
        j = 0;
        current = combs[i];
        currentLength = current.length;
        while (j < currentLength) {
            temp += current[j];
            j += 1;
        }

        if (temp <= n) {
            results.push(current);
        }

        temp = 0;
        i += 1;
    }

    return results;
}

var a = [1, 3, 6, 10, -1];

console.log(JSON.stringify(combinations(a, 9)));
[[1],[3],[6],[-1],[1,3],[1,6],[1,-1],[3,6],[3,-1],[6,-1],[10,-1],[1,3,-1],[1,6,-1],[3,6,-1],[1,3,6,-1]] 
var a = [1,3,6,10,-1];
function combinations(array, n) {
  var mask, len = array.length, count = 1 << len, permutations = [];
  var indexVisible = function(v, i) { return ((mask >> i) & 1) == 1 }
  var sum = function(a, b) { return a + b }
  for (mask = 1; mask < count; ++mask) {
    permutations.push(array.filter(indexVisible))
  }
  return permutations.filter(function(p) { return p.reduce(sum) <= n })
}
console.log(JSON.stringify(combinations(a, 9)));
/**
* Get an array of all the possible combinations
* of x items.  Combinations are represented as binary.
* @param {Number} x - example 2
* @return {String[]} - example ['00', '01', '10', '11']
*/
function getCombinationsOfXItems(x) {

  var allOn = '',
    numCombos = 0,
    i = 0,
    combos = [];

  // find upper limit
  while (allOn.length < x) {
    allOn += 1;
  }

  // number of possible combinations
  numCombos = parseInt(allOn, 2) + 1;

  // generate the combos
  while(i < numCombos) {
    combos.push(pad(toBase2(i++), allOn.length));
  }

  return combos;
}

/**
* Pad a string with leading zeros.
* @param {String} x - example '100'
* @param {Number} length - example 6
* @return {String} - example '000100'
*/
function pad(x, length) {
  while (x.length < length) {
    x = 0 + x;
  }

  return x;
}

/**
* Get a number as a binary string.
* @param {Number} x - example 3
* @return {String} - example '11'
*/
function toBase2(x) {
  return x.toString(2);
}

/**
* Given an array and a map of its items as a binary string,
* return the items identified by 1.
* @param {Array} arr - example [1,2,3]
* @param {String} binary - example '101'
* @return {Array} - example [1,3]
*/
function pluckFromArrayByBinary(arr, binary) {
  var  plucked = [],
    i = 0,
    max = binary.length;

  for (; i < max; i++) {
    if (binary[i] === '1') {
      plucked.push(arr[i]);
    } 
  }

  return plucked;
}

/**
* Given an array, return a multi-dimensional
* array of all the combinations of its items.
* @param {Array} - example [1, 2];
* @return {Array[]} - [ [1], [1, 2], [2] ]
*/
function getCombosOfArrayItems(arr) {
  var comboMaps = getCombinationsOfXItems(arr.length),
    combos = [];

  // remove the "all off" combo (ex: '00000')
  comboMaps.shift();

  for (var i = 0; i < comboMaps.length; i++) {
    combos.push(pluckFromArrayByBinary(arr, comboMaps[i]));
  }

  return combos;
}

/**
* Return all possible combinations of numbers in an
* array whose sum is less than or equal to n
* @param {Number[]} arr
* @param {Number} x
* return {Number[]} - stringified for readability
*/
function combinations(arr, x) {
  var combos = getCombosOfArrayItems(arr),
    i = 0,
    max = combos.length,
    combo;

  for (; i < max; i++) {
    if (sumArray(combos[i]) > x) {
      combos.splice(i, 1);
      i--;
      max--;
    }
  }

  return JSON.stringify(combos);
}

/**
* Return the sum of an array of numbers.
* @param {Number[]} arr
* @return {Number}
*/
function sumArray(arr) {
  var sum = 0,
    i = 0,
    max = arr.length;

  for (; i < max; i++) {
    sum += arr[i];
  }

  return sum;
}

console.log(combinations([1, 3, 6, 10, -1], 9));
function powerSet(arr) {
    var lastElement,
        val;

    if (!arr.length) {
        val = [[]];
    } else {
        lastElement = arr.pop();
        val = powerSet(arr).reduce(function (previous, element) {
            previous.push(element);
            element = element.slice();
            element.push(lastElement);
            previous.push(element);

            return previous;
        }, []);
    }

    return val;
}

function combinations(array, n) {
    return powerSet(array).filter(function (set) {
        return set.length && set.reduce(function (previous, element) {
            return previous + element;
        }, 0) <= n;
    });
}

var a = [1, 3, 6, 10, -1];

console.log(JSON.stringify(combinations(a, 9)));
[[-1],[10,-1],[6],[6,-1],[3],[3,-1],[3,6],[3,6,-1],[1],[1,-1],[1,6],[1,6,-1],[1,3],[1,3,-1],[1,3,6,-1]]