我有一个数组说,
n=3
我希望将其分成精确[1],[2],[3,4,5]
个数量的块,但其中包含所有组合。
示例:
何时[1,2],[3,4],[5]
应该返回
组合1:[1,2,3],[4],[5]
组合2:[1,2],[3],[4,5]
组合3:[1],[2,3],[4,5]
组合4:[1],[2,3,4],[5]
组合5:{{1}}
组合6:{{1}}
我无法理解从哪里开始和停止这种组合逻辑。非常感谢任何类型的指针或帮助。
答案 0 :(得分:2)
您可以使用递归方法获取所有嵌套部分,并仅迭代左侧数组的剩余长度。
基本上,如果所需数组的长度等于项目数,则需要满足退出条件。然后按结果并退出该功能。
如果没有,则迭代左侧数组并将新部件移动到临时数组。
function go(array, n) {
function iter(left, right) {
var i,
l = left.length - n + right.length + 1;
if (right.length + 1 === n) {
result.push(right.concat([left]));
return;
}
for (i = 1; i <= l; i++) {
iter(left.slice(i), right.concat([left.slice(0, i)]));
}
}
var result = [];
iter(array, []);
return result;
}
var array = [1, 2, 3, 4, 5],
n = 3,
result = go(array, n);
result.forEach(function (a) { console.log(JSON.stringify(a)); });
&#13;
答案 1 :(得分:2)
我使用的实现与Nina略有不同。
function combinations(n, values, log){
if(n > values.length)
throw new Error(`cannot divide ${values.length} items into ${n} groups`);
var results = [],
//you'll always have n items in your combination, by the very definition of this task
//this array holds the state/progress during the iterations,
//so we don't have to concat partial results all the time
//we'll push clones of the current state to the results.
combination = Array(n);
//just a utility to write a chunk to a particular index
function updateIndex(index, left, right){
combination[index] = values.slice(left, right);
log && log(index, "updateIndex(" + [index, left, right] + ")", JSON.stringify(combination[index]));
}
//And by the good old Roman principle: divide et impera
//this function always processes a subset of the array, defined by the bounds: left and right.
//where `left <= index < right` (so it doesn't include right)
//it is a recursive function, so it processes one chunk at a time, and calls itself to process the rest of the array
function divide(index, chunks, left, right){
log && log(index, "divide(" + [index, chunks, left, right] + ")", JSON.stringify(values.slice(left, right)) + " divided by " + chunks);
if(chunks > 1){
//I have to divide my section of the array in mutliple chunks
//I do that by defining a pivot
//the range where I can pivot is limited:
// - I need at least 1 item to the left for the current chunk
// - and I need at least (chunks-1) items to the right for the remaining subdivisions
for(var pivot = left + 1; pivot <= right - (chunks-1); ++pivot){
//everything on the left of this pivot is the current chunk
//write it into the combinations array at the particular index
updateIndex(index, left, pivot);
//everything on the right is not my buisness yet.
//I'll call divide() again, to take care of that
divide(index+1, chunks-1, pivot, right);
}
}else{
//this is the last chunk, write this whole section to the last index
updateIndex(index, left, right);
//push a clone of this combination to the results
//because further iterations in the loops, will change the values of the original
//to produce the remaining combinations
results.push(combination.slice());
log && log(index, "push(" + formatCombination(combination) + ")\n");
}
return results
}
return divide(0, n, 0, arr.length);
}
function formatCombination(row){
return JSON.stringify(row).replace(/\],\[/g, "], [");
}
//an utility to log the steps in a nice fashion
function logger(indentation, fnText, memo){
var str = " ".repeat(indentation) + fnText;
console.log(memo? str + " ".repeat(60-str.length) + memo: str);
}
var arr = [0,1,2,3,4,5];
var result = combinations(3, arr, logger);
console.log();
console.log( result.map(formatCombination).join("\n") )
&#13;