Given an array or object with n keys, I need to find all combinations with length x
.
Given X
is variable. binomial_coefficient(n,x)
.
Currently I'm using this:
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"]);
The output is:
["a", "ab", "abc", "abcd", "abd", "ac", "acd", "ad", "b", "bc", "bcd", "bd", "c", "cd", "d"]
So if I want the binomial coefficient x=3
from n=4
I select all the strings with length equal to three. {abc, abd, acd, bcd}.
So I do this in two steps.
Is there a more efficient algorithm with smaller complexity?
And here's the true recursion.
You could use an iterative and recursive approach with stress on the length of the array and the still needed items.
Basically
combine()
takes an array with the values to combine and a size of the wanted combination results sets.The inner function
c()
takes an array of previously made combinations and a start value as index of the original array for combination. The return is an array with all made combinations.The first call is allways
c([], 0)
, because of an empty result array and a start index of 0.We could create just those combinations we are interested in. Also, rather than cloning arrays by using slice in each call, we can use a pointer to the original array. Here's one version. Converting it to recursion without an external global variable is left as an exercise.
Your algorithm is almost
O(2^n)
, you can discard a lot of combinations, but the num of elements will be(n! * (n-x)!) / x!
.To discard the useless combinations you can use an indexed array.
For example, the first combination have the indexes:
[0, 1, 2]
and the elements["a", "b", "c"]
. To compute the next combination, It get the last index2
and try to increment, if the increment is lower than the max position (in this case4
), the next combination is reached, but if It is not, It must increment to a previous index.