From a0115aa88a45be202631cf856fad8065379c195d Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Wed, 30 Nov 2022 23:43:42 +0800 Subject: [PATCH] =?UTF-8?q?update=200257.=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E6=89=80=E6=9C=89=E8=B7=AF=E5=BE=84:=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20js=20=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F=E5=92=8C?= =?UTF-8?q?=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0257.二叉树的所有路径.md | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index 297acb60..100531cb 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -24,7 +24,7 @@ 这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。 -在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一一个路径在进入另一个路径。 +在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。 前序遍历以及回溯的过程如图: @@ -44,7 +44,7 @@ void traversal(TreeNode* cur, vector& path, vector& result) 2. 确定递归终止条件 -再写递归的时候都习惯了这么写: +在写递归的时候都习惯了这么写: ``` if (cur == NULL) { @@ -67,7 +67,7 @@ if (cur->left == NULL && cur->right == NULL) { 再来看一下终止处理的逻辑。 -这里使用vector 结构path来记录路径,所以要把vector 结构的path转为string格式,在把这个string 放进 result里。 +这里使用vector 结构path来记录路径,所以要把vector 结构的path转为string格式,再把这个string 放进 result里。 **那么为什么使用了vector 结构来记录路径呢?** 因为在下面处理单层递归逻辑的时候,要做回溯,使用vector方便来做回溯。 @@ -123,7 +123,7 @@ if (cur->right) { path.pop_back(); ``` -这个回溯就要很大的问题,我们知道,**回溯和递归是一一对应的,有一个递归,就要有一个回溯**,这么写的话相当于把递归和回溯拆开了, 一个在花括号里,一个在花括号外。 +这个回溯就有很大的问题,我们知道,**回溯和递归是一一对应的,有一个递归,就要有一个回溯**,这么写的话相当于把递归和回溯拆开了, 一个在花括号里,一个在花括号外。 **所以回溯要和递归永远在一起,世界上最遥远的距离是你在花括号里,而我在花括号外!** @@ -300,16 +300,16 @@ public: ``` -**大家应该可以感受出来,如果把 `path + "->"`作为函数参数就是可以的,因为并有没有改变path的数值,执行完递归函数之后,path依然是之前的数值(相当于回溯了)** +**大家应该可以感受出来,如果把 `path + "->"`作为函数参数就是可以的,因为并没有改变path的数值,执行完递归函数之后,path依然是之前的数值(相当于回溯了)** -**综合以上,第二种递归的代码虽然精简但把很多重要的点隐藏在了代码细节里,第一种递归写法虽然代码多一些,但是把每一个逻辑处理都完整的展现了出来了。** +**综合以上,第二种递归的代码虽然精简但把很多重要的点隐藏在了代码细节里,第一种递归写法虽然代码多一些,但是把每一个逻辑处理都完整的展现出来了。** ## 拓展 这里讲解本题解的写法逻辑以及一些更具体的细节,下面的讲解中,涉及到C++语法特性,如果不是C++的录友,就可以不看了,避免越看越晕。 -如果是C++的录友,建议本题独立刷过两遍,在看下面的讲解,同样避免越看越晕,造成不必要的负担。 +如果是C++的录友,建议本题独立刷过两遍,再看下面的讲解,同样避免越看越晕,造成不必要的负担。 在第二版本的代码中,其实仅仅是回溯了 `->` 部分(调用两次pop_back,一个pop`>` 一次pop`-`),大家应该疑惑那么 `path += to_string(cur->val);` 这一步为什么没有回溯呢? 一条路径能持续加节点 不做回溯吗? @@ -378,7 +378,7 @@ public: 最后我依然给出了迭代法。 -对于本地充分了解递归与回溯的过程之后,有精力的同学可以在去实现迭代法。 +对于本题充分了解递归与回溯的过程之后,有精力的同学可以再去实现迭代法。 @@ -386,7 +386,7 @@ public: # 其他语言版本 -Java: +## Java: ```Java //解法一 @@ -466,7 +466,7 @@ class Solution { } ``` --- -Python: +## Python: 递归法+隐形回溯 ```Python3 # Definition for a binary tree node. @@ -529,7 +529,7 @@ class Solution: --- -Go: +## Go: 递归法: @@ -591,28 +591,28 @@ func binaryTreePaths(root *TreeNode) []string { ``` --- -JavaScript: +## JavaScript: 递归法: ```javascript var binaryTreePaths = function(root) { //递归遍历+递归三部曲 - let res=[]; + let res = []; //1. 确定递归函数 函数参数 - const getPath=function(node,curPath){ + const getPath = function(node,curPath) { //2. 确定终止条件,到叶子节点就终止 - if(node.left===null&&node.right===null){ - curPath+=node.val; + if(node.left === null && node.right === null) { + curPath += node.val; res.push(curPath); - return ; + return; } //3. 确定单层递归逻辑 - curPath+=node.val+'->'; - node.left&&getPath(node.left,curPath); - node.right&&getPath(node.right,curPath); + curPath += node.val + '->'; + node.left && getPath(node.left, curPath); + node.right && getPath(node.right, curPath); } - getPath(root,''); + getPath(root, ''); return res; }; ``` @@ -644,7 +644,7 @@ var binaryTreePaths = function(root) { }; ``` -TypeScript: +## TypeScript: > 递归法 @@ -698,7 +698,7 @@ function binaryTreePaths(root: TreeNode | null): string[] { }; ``` -Swift: +## Swift: > 递归/回溯 ```swift @@ -765,7 +765,7 @@ func binaryTreePaths(_ root: TreeNode?) -> [String] { } ``` -Scala: +## Scala: 递归: ```scala