[英]How does this recursive array permutation function work under the hood?
此函數生成數組的排列。 我已經用紙筆在開發工具中添加了斷點,並且精心地逐步完成了每個函數調用,但我仍然不明白這是如何工作的。
具體來說,for循環。 一旦do It函數拼接出數組中的所有數字,它就會將臨時數組的切片副本推送到應答數組中。 然后它將item拼接到參數數組中,從temp數組中彈出相同的項,並返回for循環的第一次迭代的答案。 因此,在循環數組一次之后,答案= [1,2,3] temp = [1,2]和arr = [3]。
這是我迷路的地方。 它似乎跳回到接頭並拼接2回到arr。 在devTools中,我把手表放在i,item,temp和arr上。 它說我在某種程度上變成了1,即使在我們將3拼接回來之后,arr中只有一個項目。 如果長度為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]));
謝謝!
一般來說,我不是使用斷點來跟蹤這些,而是使用print語句。 當我輸入函數時,我打印函數名稱和參數值。 當我離開時,我打印名稱並退出(返回和狀態)值。 在這種情況下,我會在循環中做同樣的事情。 現在,讓我們看看更像英語的偽代碼
依次對於每個數組元素:從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調用:第一個遍歷項[0]的所有3個可能選項; 第二個遍歷項[1]的2個可能選項,第三個選擇剩余元素,記錄排列,然后備份到第二個調用。 每個調用實例都維護其本地值i,len和item 。
對於您的具體問題,當前三個調用標識[1,2,3]作為解決方案時,狀態如下所示:
堆:
doIt ,i = 0,len = 3,item = 1
我們現在返回上一個呼叫,#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),為temp選擇2 ,然后我們從以2開始的答案開始。
這足以讓你獲得這個想法嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.