为啥我的排列算法对所有排列都给出相同的结果?

Posted

技术标签:

【中文标题】为啥我的排列算法对所有排列都给出相同的结果?【英文标题】:Why is my permutation algorithm giving me the same result for all permutations?为什么我的排列算法对所有排列都给出相同的结果? 【发布时间】:2018-01-19 06:51:21 【问题描述】:

我被一些堆的排列算法困住了。我编写了一些 javascript 代码以递归方式查找值的所有可能排列:数组或字符串。当我console.log() 置换值时,我的代码似乎可以完美运行,但是当我将它们推送到另一个数组时,我得到的所有值都相同。我很困惑。

我的代码包含两个独立的函数:一个是交换元素,另一个是递归查找可能的排列:

arr = ["a", "b", "c"];
newArr = [];

// swap mechanism here
function swap(arr, pos1, pos2) 
    var temp = arr[pos1];
    arr[pos1] = arr[pos2];
    arr[pos2] = temp;
;

function perm(arr, nArr, n) 
    n = n || arr.length; 
    if (n === 1) 
        console.log(arr); // console.log() works great
        newArr.push(arr); // pushing the permuted values does not
    
    else 
        for(var i = 1; i <= n; i += 1) 
            perm(arr, nArr, n - 1);
            if (n % 2) 
                var j = 1;
            
            else 
                var j = i;
            
            swap(arr, j - 1, n - 1);
        
    
;

【问题讨论】:

欢迎来到 ***。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。 【参考方案1】:

这是一个简单的(堆)引用与(堆栈)值的问题。原因很简单:arr 在所有递归调用中都引用了内存中的同一个数组。因此,当您调用newArr.push(arr) 时,对同一对象的另一个引用将添加到结果列表中。而当您执行swap 时,您会将元素交换为newArr 的所有元素,因为它们指向同一个数组。另请参阅Copying array by value in JavaScript 了解可能的解决方法。 (基本上是用Array.slice的方法来创建一个独立的副本)。

【讨论】:

非常感谢,兄弟。我很困惑,但我想我明白问题所在。一个快速的问题:console.log() 怎么会显示所有排列的值?我不太明白那部分。 @WadsonFourrien, console.log 显示执行时的当前值。那时(唯一的)数组处于您想要的状态(并且来自newArr 的所有引用都指向该状态下的同一个数组)。但是,当您下次调用swap 时修改该(相同的)数组,它的状态现在与您上次记录的不同。设置断点并在第 3 次或第 4 次迭代中查看 newArr 以了解它如何包含对同一内存的多个引用可能会有所帮助。

以上是关于为啥我的排列算法对所有排列都给出相同的结果?的主要内容,如果未能解决你的问题,请参考以下文章

没有重复的排列算法?

为啥“StratifiedShuffleSplit”对数据集的每个拆分都给出相同的结果?

Python排列组合简单算法实现

C语言全排列问题为啥用指针比数组慢很多?

有重复元素的排列问题

蓝桥杯上的一题,题目为排列数,用了暴力算法超时,请问该怎么处理,谢谢!