You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于JavaScript回溯算法的困惑:排列问题执行流程疑问

回溯算法排列问题执行流程困惑

我近期在学习JavaScript中的回溯算法时感到十分困惑,尤其聚焦于排列问题——给定一个数组,生成其所有可能的排列。以下是相关实现代码:

function permute(nums) {
    let result = [];
    function backtrack(temp = []) {
        if (temp.length === nums.length) {
            result.push([...temp]);  
            return;
        }
        for (let i = 0; i < nums.length; i++) {
            if (temp.includes(nums[i])) continue;  
            temp.push(nums[i]);       
            backtrack(temp);          
            temp.pop();               
        }
    }
    backtrack();
    return result;
}

为简化分析,我以nums = [1,2]为例。我的理解是:初始temp为空数组,当i=0时temp变为[1],调用backtrack寻找剩余值2;随后i=1时temp变为[1,2],满足长度条件,将该数组的副本加入result。我的疑问是:将[1,2]加入result后,后续代码的执行流程是怎样的?

已知这段代码能正确返回[[1,2],[2,1]],但我无法理解其逻辑。我以为加入[1,2]后,temp会弹出最后一个元素变为[1],然后循环重新执行,但这样会再次添加2并重复判断长度,无法得到[2,1]的结果。我知道自己的理解存在偏差,但不清楚问题出在哪里。


执行流程拆解(以nums=[1,2]为例)

咱们一步步拆解每一步的执行逻辑:

  1. 初始调用:执行backtrack(),此时temp = [],进入循环i=0:

    • temp不包含1,执行temp.push(1),temp变为[1],调用backtrack([1])。
  2. 第一次递归调用:backtrack([1]),temp.length=1不等于2,进入循环:

    • i=0:temp.includes(1)为真,跳过当前循环;
    • i=1:temp不包含2,执行temp.push(2),temp变为[1,2],调用backtrack([1,2])。
  3. 第二次递归调用:backtrack([1,2]),temp.length=2等于nums.length,执行result.push([...temp]),result变为[[1,2]],随后return退出当前函数。

  4. 回到第一次递归的i=1分支:

    • 退出backtrack([1,2])后,执行temp.pop(),temp变回[1];
    • 循环i=1执行完毕,整个循环结束,退出第一次递归的backtrack函数。
  5. 回到初始调用的i=0分支:

    • 退出第一次递归后,执行temp.pop(),temp变回[];
    • 循环继续执行i=1:
      • temp不包含2,执行temp.push(2),temp变为[2],调用backtrack([2])。
  6. 第三次递归调用:backtrack([2]),temp.length=1不等于2,进入循环:

    • i=0:temp不包含1,执行temp.push(1),temp变为[2,1],调用backtrack([2,1])。
  7. 第四次递归调用:backtrack([2,1]),temp.length=2等于nums.length,执行result.push([...temp]),result变为[[1,2],[2,1]],return退出当前函数。

  8. 回到第三次递归的i=0分支:

    • 退出后执行temp.pop(),temp变回[2];
    • i=1:temp.includes(2)为真,跳过;
    • 循环结束,退出第三次递归函数。
  9. 回到初始调用的i=1分支:

    • 退出后执行temp.pop(),temp变回[];
    • 循环结束,退出初始的backtrack函数;
    • 最终返回result,即[[1,2],[2,1]]。

你的误区在于:误以为从[1,2]返回后,会在第一次递归的循环里重复执行,但实际上第一次递归的循环i已经走到末尾,执行完pop后直接退出该递归函数,回到初始调用的循环,继续执行i=1的分支——这正是生成[2,1]的核心步骤。


内容的提问来源于stack exchange,提问作者ContravariantMind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:42:08