ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript-此递归数组置换函数如何在后台运行?

2019-10-26 19:42:14  阅读:156  来源: 互联网

标签:permutation arrays javascript algorithm recursion


此函数生成数组的排列.我已经花了很多笔钱,并在开发工具中设置了断点,并辛苦地逐步完成了每个函数的调用,但是我仍然不了解这是如何工作的.

具体来说,是for循环.一旦do It函数将数组中的所有数字拼接起来,就会将temp数组的切片副本推入答案数组.然后,它将项目拼接到参数数组中,从temp数组中弹出相同的项目,并返回for循环的第一次迭代的答案.因此,在循环遍历一次数组后,答案= [1,2,3],温度= [1,2],arr = [3].

这是我迷路的地方.似乎跳回了接头,接头2又回到了arr.在devTools中,我监视了i,item,temp和arr.它说即使我们将3拼接回去之后,即使在arr中只有一项,我仍然以某种方式变为1.如果长度为1,并且for循环指定它应在arr.length处停止运行,它如何以某种方式跳回并拼接2回到数组中?

很抱歉,我的措词不连贯.今天我花了很多时间来解决这个问题.

Tdlr.运行此功能.在do It函数的for循环上放置一个断点.数组为空后,我们返回答案,它将如何将两个项目拼接回原始的arr中.

function permute(arr) {
    var temp = [];
    var answer = [];

    function logResult() {
      answer.push(
        // make a copy of temp using .slice()
        // so we can continue to work with temp
        temp.slice()
      );
    }

    function doIt() {
      var i;
      var len;
      var item;

      for (i = 0, len = arr.length; i < len; i++) {
        // remove the item at index i
        item = arr.splice(i, 1)[0];
        // add that item to the array we're building up
        temp.push(item);
        if (arr.length) {
          // if there's still anything left in the array,
          // recurse over what's left
          doIt();
        } else {
          // otherwise, log the result and move on
          logResult();
        }
        // restore the item we removed at index i
        // and remove it from our temp array
        arr.splice(i, 0, item);
        temp.pop();  
      }
      return answer;
    }
  return doIt();
};

console.log(permute([1,2,3]));

谢谢!

解决方法:

通常,我不使用断点而是使用打印语句来跟踪它们.
输入函数时,我将打印函数名称和参数值.离开时,我将打印名称并退出(返回和状态)值.在这种情况下,我将在循环内执行相同的操作.现在,让我们用更像英语的伪代码来看看

对于每个数组元素依次:
    从arr删除该元素并将其附加到项目
    如果我们清空了arr
        日志项作为下一个排列
    其他
        在arr中减少一个元素,在项目中再增加一个元素

// When we reach this point, we've exhausted all the permutations that
//   begin with the original state of **item**.
// Back up one element
take the chosen element from **item** and re-append it to **arr**.
// Go to the next loop iteration, which will move to the next element.

在完成此过程时,请记住在运行时堆栈上有多个doIt调用:第一个遍历item [0]的所有3种可能选择;第二个遍历item [1]的2个可能选择,第三个遍历其余元素,记录排列,然后备份到第二个调用.每个调用实例都维护其本地值i,len和item.

对于您的特定问题,当前三个调用将[1、2、3]标识为解决方案时,状态如下:

堆:

> doIt,i = 0,len = 1,item = 3
> doIt,i = 0,len = 2,item = 2
> doIt,i = 0,len = 3,item = 1

> arr = [3],temp = [1,2]

现在我们返回到上一个调用#2,将调用#3从堆栈中弹出.
在此调用中,我们刚刚从#3 doIt调用返回.我们跳到还原点,将2拼接回arr,然后迭代到循环的顶部.

将i增量为1,从arr中选择值3,剩下temp = [1,3]和arr = 2.重复执行doIt,另一个电话#3 …

…选择剩余的2,记录解决方案[1、3、2],将2放回arr,然后返回到调用#2.

调用#2将3剪接回arr,进行迭代,将i递增为2,现在n已耗尽其for循环.它将1拼接回arr并返回到调用#1.

现在,我们有temp = [],arr = [1、2、3],并且只有我们原来的doIt调用在堆栈上.前进到下一个循环迭代(i = 1),为2选择2
临时,我们从以2开头的答案开始.

足够的追踪让您理解吗?

标签:permutation,arrays,javascript,algorithm,recursion
来源: https://codeday.me/bug/20191026/1939153.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有