我需要创建一个数组元素的所有可能组合的数组,例如排列变化广泛的数据结构问题。要了解有关问题的更多信息,请在random hacks,geeksforgeeks和math world处进行检查。
注意:不想使用任何JS库,只需此处的数据结构
问题很简单,提供了一个数组,需要查找所有可能的组合,例如:
arr = [1,2,3];
combination = [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]];
// combination.length is factorial of arr.length
要达到这个目的,我创建了一个全局变量来存储组合,需要在没有全局变量的情况下完成,我无法做到这一点,任何人都可以帮助我解决这个问题,这是我的代码:
let ans = []; // Global variable to store combinations
function permute(arr) {
let l = arguments[1] || 0,
r = arguments[2] || arr.length-1;
if (l == r) {
let a = [];
a.push(...arr); // To overcome reference problem here.
ans.push(a);
}
else {
for (let i = l; i <= r; i++) {
[arr[l], arr[i]] = [arr[i], arr[l]]; // Swap with help of new destructuring
permute(arr, l+1, r);
[arr[l], arr[i]] = [arr[i], arr[l]]; // Swap with help of new destructuring
}
}
return ans;
}
console.log(permute([1,2,3,4]));
console.log(permute([1,2,3]));
console.log(permute([1,2,3,4,5]));
感谢您的尝试和帮助。
答案 0 :(得分:2)
您正在进行递归而没有通过累加器。要减轻这种情况,请执行...
function permuteRecursive(permutees, accumulator) {
// if not created before, create first instance of accumulator
accumulator = accumulator || [];
let l = arguments[2] || 0,
r = arguments[3] || permutees.length-1;
if (l == r) {
let a = [];
a.push(...permutees); // To overcome reference problem here.
accumulator.push(a);
}
else {
for (let i = l; i <= r; i++) {
[permutees[l], permutees[i]] = [permutees[i], permutees[l]]; // Swap with help of new destructuring
permuteRecursive(permutees, accumulator, l+1, r);
[permutees[l], permutees[i]] = [permutees[i], permutees[l]]; // Swap with help of new destructuring
}
}
return accumulator;
}
console.log(permuteRecursive([1,2,3,4]));
console.log(permuteRecursive([1,2,3]));
console.log(permuteRecursive([1,2,3,4,5]));
答案 1 :(得分:2)
我将使用附加参数将当前选择的元素传递给函数,并使用生成器将所有结果传递回去:
function* permutations(array, positions = [], previous = []) {
if(previous.length === array.length) yield previous;
for(let i = 0; i < array.length; i++) {
if(positions.includes(i)) continue;
const chosen = array[i];
yield* permutations(array, [...positions, i], [...previous, chosen]);
}
}
const permutate = arr => [...permutations(arr)];
答案 2 :(得分:1)
如果唯一需要关注的是全局变量,则可以将其包装在另一个函数中,我的意思是以下内容:
function permute(_arr) {
let ans = [];
(function _permute(arr) {
let l = arguments[1] || 0,
r = arguments[2] || arr.length - 1;
if (l == r) {
let a = [];
a.push(...arr); // To overcome reference problem here.
ans.push(a);
}
else {
for (let i = l; i <= r; i++) {
[arr[l], arr[i]] = [arr[i], arr[l]]; // Swap with help of new destructuring
_permute(arr, l + 1, r);
[arr[l], arr[i]] = [arr[i], arr[l]]; // Swap with help of new destructuring
}
}
})(_arr);
return ans;
}
console.log(permute([1, 2, 3, 4]));
console.log(permute([1, 2, 3]));
console.log(permute([1, 2, 3, 4, 5]));
答案 3 :(得分:1)
您还可以尝试将Array.map
与递归结合使用,如下所示,以实现置换。我还使用过Array.flat
(到目前为止,Edge不支持,如果要支持Edge浏览器,则需要使用polyfill)
function getForwardArr(arr, i) {
return [...arr.slice(i+1), ...arr.slice(0, i)]
}
function permute(arr) {
if (arr.length == 2) return [[...arr], arr.reverse()]
else return arr.map((d, i) => permute(getForwardArr(arr, i)).map(v => [d, v].flat())).flat()
}
console.log(permute([1,2]))
console.log(permute([1,2,3]))
console.log(permute([1,2,3,4]))
答案 4 :(得分:0)
执行此操作的另一种方法是不传递任何信息,而是重用较小的子问题的结果来构建排列数组并返回。
例如,要构建所有3个元素置换,您可以将每个元素放在第一位,并将其与其余元素的所有2个元素置换连接起来(您可以通过递归调用获得):
function permutations(arr) {
if (arr.length <= 1) return [arr];
var res = [];
arr.forEach((e, i) => {
var smaller = permutations([...arr.slice(0, i), ...arr.slice(i + 1)]);
smaller.forEach(p => res.push([e].concat(p)))
});
return res;
}
console.log(permutations([1]));
console.log(permutations([1, 2, 3]));