蕭十郎
2022-10-27 14:26:32
我有一個非常受開發人員歡迎的算法練習,它返回:steps(3)######steps(5)###############我正在研究以遞歸方式開發的版本。下面的代碼工作正常。function steps(n, row = 0 , stair = '') { if(n === row) { return; } if(n === stair.length) { console.log(stair) return steps(n, row + 1) } if (stair.length <= row) { stair += '#'; } else { stair += ' ' } steps(n, row, stair)}steps(3)我唯一的疑問與這部分代碼中“返回”的重要性有關: if(n === stair.length) { console.log(stair) return steps(n, row + 1) // <--- this 'return' }如果我刪除'return',像這樣:if(n === stair.length) { console.log(stair) steps(n, row + 1) // <-- without the return}這會在控制臺上生成一個循環錯誤:超出最大調用堆棧大小我想了解為什么會發生這種情況。我仍然沒有太多的遞歸函數練習。
3 回答

慕桂英4014372
TA貢獻1871條經驗 獲得超13個贊
它中斷是因為您的代碼在 row === n 時終止。那條線是唯一改變行的地方。沒有它,代碼將產生如下輸出:
#
#
#
#
#
...
由于您在遞歸函數中處理此問題,因此 javascript 在它變得無限深之前會用完堆棧幀。

烙印99
TA貢獻1829條經驗 獲得超13個贊
有兩種方法可以考慮遞歸函數。首先是實際查看實際發生的情況——也就是說,查看一個示例并通過注意對函數的所有調用來“展開” steps
。這很安全,也很容易。
第二種方式更“神奇。在這種思維方式中,您不會考慮“大局”或考慮遞歸函數的多次調用。相反,您形成了一個連貫的想法,即您的遞歸函數應該接受什么作為參數和它應該返回什么。然后,您始終可以按照您認為它應該工作的方式使用該函數來編寫遞歸函數的主體。這可能會更加令人困惑,但是一旦您“獲得”它,它就會非常優雅并且是更有用的思維方式。
讓我們在這里使用第一種思維方式,因為它可能更容易。steps
你能告訴我按順序調用了多少次以及使用哪些參數?例如,第一個調用是steps(5, 0, '')
. 那么,第二次調用steps
會發生什么?按照這些步驟(呵呵),您應該會看到問題所在。
添加回答
舉報
0/150
提交
取消