此函数生成数组的排列.我已经花了很多笔钱,并在开发工具中设置了断点,并辛苦地逐步完成了每个函数的调用,但是我仍然不了解这是如何工作的.
具体来说,是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开头的答案开始.
足够的追踪让您理解吗?