给定一个带有n个键的数组或对象,我需要找到长度为 x
的所有组合 .
鉴于 X
是可变的 . binomial_coefficient(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"]
因此,如果我想要 n=4
的二项式系数 x=3
,我选择长度等于3的所有字符串 . {abc,abd,acd,bcd} .
所以我分两步完成 .
是否有更高效的算法,复杂度更低?
4 回答
你的算法几乎是
O(2^n)
,你可以丢弃很多组合,但是元素的数量将是(n! * (n-x)!) / x!
.要丢弃无用的组合,您可以使用索引数组 .
例如,第一个组合具有索引:
[0, 1, 2]
和元素["a", "b", "c"]
. 要计算下一个组合,它得到最后一个索引2
并尝试递增,如果增量低于最大位置(在本例中为4
),则到达下一个组合,但如果不是,则必须增加到a以前的指数 .您可以使用迭代和递归方法,同时强调数组的长度和仍然需要的项目 .
基本上
combine()
采用一个数组,其中包含要组合的值和所需组合结果集的大小 .内部函数
c()
采用先前组合的数组和起始值作为原始数组的索引进行组合 . 返回是一个包含所有组合的数组 .第一个调用是allways
c([], 0)
,因为结果数组为空,起始索引为0 .我们可以创建我们感兴趣的组合 . 而且,不是通过在每次调用中使用切片来克隆数组,我们可以使用指向原始数组的指针 . 这是一个版本 . 将它转换为没有外部全局变量的递归是一个练习 .
这是真正的递归 .