当前位置: 首页 > 知识库问答 >
问题:

获取对象中所有项目组合的高效算法

长孙雅志
2023-03-14

给定一个具有n个键的数组或对象,我需要找到长度x的所有组合
给定的X是可变的二项式效率(n,x)

目前我正在使用这个:

function combine(items) {
    var result = [];
    var f = function(prefix, items) {
        for (var i = 0; i < items.length; i++) {
            result.push(prefix + items[i]);
            f(prefix + items[i], items.slice(i + 1));
        }
    }
    f('', items);
    return result;
}

var combinations = combine(["a", "b", "c", "d"]);

输出为:

["a", "ab", "abc", "abcd", "abd", "ac", "acd", "ad", "b", "bc", "bcd", "bd", "c", "cd", "d"]

因此,如果我想从< code>n=4中得到二项式系数< code>x=3,我选择所有长度等于3的字符串。{abc,abd,acd,bcd}。

所以我分两步做。

有没有一种复杂度更小、效率更高的算法?

链接: 解决方案性能 (JSPerf)

共有3个答案

华俊弼
2023-03-14

我们可以创建我们感兴趣的那些组合。此外,我们可以使用指向原始数组的指针,而不是在每次调用中使用切片来克隆数组。这是一个版本。在没有外部全局变量的情况下将其转换为递归是一个练习。

function choose(ns,r){
  var res = [];

  function _choose(i,_res){
    if (_res.length == r){
      res.push(_res);
      return;

    } else if (_res.length + ns.length - i == r){
      _res = _res.concat(ns.slice(i));
      res.push(_res);
      return
    }

    var temp = _res.slice();
    temp.push(ns[i]);

    _choose(i + 1,temp);
    _choose(i + 1,_res);
  }

  _choose(0,[]);
  return res;
}

var combinations = choose(["a", "b", "c", "d"], 3);
console.log(JSON.stringify(combinations));
廉博赡
2023-03-14

您可以使用迭代和递归方法,强调数组的长度和仍然需要的项目。

基本上 combine() 需要一个数组,其中包含要组合的值和所需组合结果集的大小。

内部函数< code>c()接受一个先前组合的数组和一个起始值作为组合的原始数组的索引。返回的是一个包含所有组合的数组。

第一个调用是allways c([],0),因为结果数组为空,起始索引为0。

function combine(array, size) {

    function c(part, start) {
        var result = [], i, l, p;
        for (i = start, l = array.length; i < l; i++) {
            p = part.slice(0);                       // get a copy of part
            p.push(array[i]);                        // add the iterated element to p
            if (p.length < size) {                   // test if recursion can go on
                result = result.concat(c(p, i + 1)); // call c again & concat rresult
            } else {
                result.push(p);                      // push p to result, stop recursion
            }
        }
        return result;
    }

    return c([], 0);
}

console.log(combine(["a", "b", "c", "d"], 3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
党星鹏
2023-03-14

你的算法几乎是O(2^n),你可以丢弃很多组合,但元素的数量将是(n!*(n-x)!)/ x!

要丢弃无用的组合,可以使用索引数组。

 function combine(items, numSubItems) {
        var result = [];
        var indexes = new Array(numSubItems);
        for (var i = 0 ; i < numSubItems; i++) {
            indexes[i] = i;
        }
        while (indexes[0] < (items.length - numSubItems + 1)) {
            var v = [];
            for (var i = 0 ; i < numSubItems; i++) {
                v.push(items[indexes[i]]);
            }
            result.push(v);
            indexes[numSubItems - 1]++;
            var l = numSubItems - 1; // reference always is the last position at beginning
            while ( (indexes[numSubItems - 1] >= items.length) && (indexes[0] < items.length - numSubItems + 1)) {
                l--; // the last position is reached
                indexes[l]++;
                for (var i = l +1 ; i < numSubItems; i++) {
                    indexes[i] = indexes[l] + (i - l);
                }
            }        
        }
        return result;
    }

    var combinations = combine(["a", "b", "c", "d"], 3);
    console.log(JSON.stringify(combinations));
 类似资料:
  • 使用Spark,我的算法的中间步骤之一将输出(键、向量)到pairrdd。在这一步完成之后,我希望生成所有可能的键的2-组合,并对它们的值执行进一步的操作,即我希望有一个带有((Key1,Key2),(Vector1,Vector2))的PairRDD。 关于如何以可伸缩的方式实现这一点,有什么想法吗?我想不通。谢谢!!

  • 问题内容: 现在,我正在尝试编写一个函数,该函数接受一个数组和一个整数n,并给出每个大小为n的组合的列表(因此为一个int数组的列表)。我可以使用n个嵌套循环来编写它,但这仅适用于特定大小的子集。我不知道如何将其推广到任何规模的组合。我想我需要使用递归吗? 这是3个元素的所有组合的代码,我需要一个任意数量的元素的算法。 问题答案: 这是生成所有k子集或k组合的经过充分研究的问题,无需递归即可轻松完

  • 我想从数据数组中获得所有名称。有没有什么方法可以不用迭代器来做呢?

  • 问题内容: 这可能是一个愚蠢的问题,但是考虑到以下指示: 我将如何获得此列表: 换句话说,我希望字典中两个键/值对的所有组合都不能替换,而与顺序无关。 问题答案: 一种解决方案是使用: 编辑 :由于受欢迎的需求,这里是Python 3.x版本:

  • 编辑问题以包含所需的行为、特定问题或错误以及重现问题所需的最短代码。这将帮助其他人回答问题。 现在我正在尝试编写一个函数,它接受一个数组和一个整数n,并给出每个大小n组合的列表(因此是一个int数组列表)。我可以使用n个嵌套循环编写它,但这仅适用于特定大小的子集。我不知道如何将其推广到任何大小的组合。我想我需要使用递归? 这是3个元素的所有组合的代码,我需要一个适用于任意数量元素的算法。

  • 问题内容: 我有一个字符数组c [] [],每个索引都有不同的映射。例如: 我需要以字符串形式返回此数组的所有可能字符组合。也就是说,对于上述字符数组,我应该返回:“ ag”,“ ah”,“ ai”,“ bg”,“ bh”,“ bi”,“ cg”,“ ch”,“ ci”等对于上面只有两件事的字符数组,这样做很容易,但是如果有更多的数组,那么我不知道该怎么办…这就是我要大家提供的帮助!:) 问题答案