查找数组元素的所有组合(JavaScript)

查找数组元素的所有组合(JavaScript),javascript,arrays,algorithm,recursion,combinations,Javascript,Arrays,Algorithm,Recursion,Combinations,我试图编写一个JavaScript函数,返回未知长度数组中所有元素的组合。传递给函数的参数应该是一个单位数字符串数组,例如[5,7,9] 所需功能示例: 如果传入[5,7,9]的数组,它将返回一个包含这3个数字的所有可能的3位组合的数组,即[579,759,957,795,…] 如果传入[2,5,4,6]的数组,则会得到这4个数字的4位组合,即[2546,2654,2465,…] 如果您传入一个长度为5的数组,您将得到这5个数字的5位组合。。。 等等 如果输入的数组多次具有相同的数字,则该数字应

我试图编写一个JavaScript函数,返回未知长度数组中所有元素的组合。传递给函数的参数应该是一个单位数字符串数组,例如[5,7,9]

所需功能示例:

如果传入[5,7,9]的数组,它将返回一个包含这3个数字的所有可能的3位组合的数组,即[579,759,957,795,…] 如果传入[2,5,4,6]的数组,则会得到这4个数字的4位组合,即[2546,2654,2465,…] 如果您传入一个长度为5的数组,您将得到这5个数字的5位组合。。。 等等 如果输入的数组多次具有相同的数字,则该数字应在结果数组中出现多次,例如[5,5,6]转到[556,655,565,…] 我环顾四周,似乎递归可能是一种方法,但我正在努力让它工作。我尝试了下面的解决方案,目前适用于3位数字,但我不知道如何制作一个适用于未知长度数组的函数

如果有人能帮助我,我将不胜感激:

function getDoubleDigitCombinations(input) {
    let result = [];

    const first = input[0];
    const last = input[1];

    result.push(first + last);
    result.push(last + first);
    
    return result;
}


function getTripleDigitCombinations(input) {
    let result = [];
    
    let main; //This is the number in question
    let other1; // These are the other numbers
    let other2;

    for(i = 0; i < input.length; i++) {
        
        let arr = input.slice();        // Make a copy of the input array
        main = input[i];

        arr.splice(i, 1);       // remove the main element from the array
        other1 = arr[0];        // so that you are left with the other two numbers
        other2 = arr[1];

        console.log(`Main is ${main}`);
        console.log(`other1 is ${other1} and other2 is ${other2}`);

        const arr2 = getDoubleDigitCombinations([other1, other2]);      // get the combinations of the others

        result.push(main + arr2[0]);        // concatenate main with both of the others combinations
        result.push(main + arr2[1]);
    }

    return result;
}

let result2 = getTripleDigitCombinations(["6", "7", "8"]);
console.log("result2 is ...")
for(i = 0; i < result2.length; i++) {
    console.log(result2[i]);
}
可以用于生成所有排列而不重复数组元素,然后可以将这些排列与array.join一起使用以将它们转换为字符串。这适用于任何大小和类型的阵列:

下面是一个快速javascript实现:

// some global variable to store the results
var result = []

// currentSize should be invoked with the array size
function permutation(arr, currentSize) {
    if (currentSize == 1) { // recursion base-case (end)
        result.push(arr.join(""));
        return;
    }
    
    for (let i = 0; i < currentSize; i++){
        permutation(arr, currentSize - 1);
        if (currentSize % 2 == 1) {
            let temp = arr[0];
            arr[0] = arr[currentSize - 1];
            arr[currentSize - 1] = temp;
        } else {
            let temp = arr[i];
            arr[i] = arr[currentSize - 1];
            arr[currentSize - 1] = temp;
        }
    }
}

let array = ["1","2","3","4"];
permutation(array, array.length);

console.log(result);
// use result here
请记住,这在计算上非常昂贵,其复杂性为On

可用于生成所有排列,而无需重复数组元素,然后可将这些排列与array.join一起使用,将其转换为字符串。这适用于任何大小和类型的阵列:

下面是一个快速javascript实现:

// some global variable to store the results
var result = []

// currentSize should be invoked with the array size
function permutation(arr, currentSize) {
    if (currentSize == 1) { // recursion base-case (end)
        result.push(arr.join(""));
        return;
    }
    
    for (let i = 0; i < currentSize; i++){
        permutation(arr, currentSize - 1);
        if (currentSize % 2 == 1) {
            let temp = arr[0];
            arr[0] = arr[currentSize - 1];
            arr[currentSize - 1] = temp;
        } else {
            let temp = arr[i];
            arr[i] = arr[currentSize - 1];
            arr[currentSize - 1] = temp;
        }
    }
}

let array = ["1","2","3","4"];
permutation(array, array.length);

console.log(result);
// use result here

请记住,这在计算上非常昂贵,其复杂性为On

我相信,希普的算法仍然是效率的黄金标准。维克托的回答涵盖了这一点

但由于任何算法都必须至少打开!,我们永远不会在生成置换时获得惊人的性能。我们可能还想看看简单性

另一个实现显然更简单:

常数不包括=i=>xs=> […xs.slice 0,i,…xs.slice i+1] 常量置换=xs=> xs.length==0 ? [[]] :xs.flatMap x,i=>不包括i xs.map p=>x+p的置换
log permutations['5','6','7']我相信,Heap的算法仍然是效率的黄金标准。维克托的回答涵盖了这一点

但由于任何算法都必须至少打开!,我们永远不会在生成置换时获得惊人的性能。我们可能还想看看简单性

另一个实现显然更简单:

常数不包括=i=>xs=> […xs.slice 0,i,…xs.slice i+1] 常量置换=xs=> xs.length==0 ? [[]] :xs.flatMap x,i=>不包括i xs.map p=>x+p的置换
控制台。日志排列['5','6','7']一个有趣的问题!我想使用生成器实现。这允许您在生成排列时逐个处理排列,而不必在提供完整答案之前计算所有排列-

常量输入=
[一个有趣的问题!我想使用生成器实现。这允许您在生成置换时逐个处理置换,而不必在提供完整答案之前计算所有置换-

常量输入=
[欢迎来到StackOverflow!如果有重复的数字,你会期望发生什么?答案中会有重复的组合,还是每个答案只出现一次?顺便说一句,你应该在网站上搜索相关答案。有什么帮助吗?@ScottSauyet很好。应该在输出数组中重复。感谢你指出out,我已经更新了问题以反映这一点!我明天会查看这些答案,谢谢Scotty你在寻找排列,而不是组合。啊,是的,你是对的,谢谢你Alexey:欢迎来到StackOverflow!如果有重复的数字,你会期望发生什么?答案中会有重复的组合,还是each只出现一次?顺便说一句,你应该在网站上搜索相关答案。你有什么帮助吗?@ScottSauyet很好的观点。应该在输出数组中重复。谢谢你指出这一点,我已经更新了问题以反映这一点!我明天会查看这些答案,谢谢ScottYou正在寻找排列,而不是组合。啊,是的你说得对,谢谢Alexey:非常感谢Viktor!这非常有效。对于任何其他学习者,我会推荐这段帮助我理解算法的视频。非常感谢Viktor!这非常有效。对于任何其他学习者,我会推荐这段帮助我理解算法的视频,你可能已经看过了:D我
喜欢你的名字旋转,并同意它作为自己的功能是有用的。如果你不这样做,我会分解我的名字,接受你的名字mind@Thank你我当然不介意。这就是它的目的:互相学习,互相借钱,互相偷窃。如果有会计的话,我对你的债务要比你的债务深得多。是的,你的算法是一样的,但我确实在想,我一定在最近的排列搜索中看过。所以你实际上采用了Chris Vouga的术语。哈哈,这方面没有核算。我明白我来这里的目的,而你在其中扮演了重要角色,所以继续并永远感谢斯科特。我现在正在研究一种迭代排列,它可以缓慢地产生结果,这比我想象的更具挑战性。我将向您通报我取得的进展:D@Thankyou:如果您只想使用生成函数,我的第一种方法可以很容易地修改:函数*置换xs{If xs.length==0 yield[];对于let i=0;对于let p的置换,i