From 770babda32822cc9dd7d5a66b5971bbbd97d0c44 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 11:13:58 +0800 Subject: [PATCH 01/13] =?UTF-8?q?update=200654.=E6=9C=80=E5=A4=A7=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=A0=91:=20=E6=9B=B4=E6=96=B0=20go=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0654.最大二叉树.md | 34 +++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md index fda64372..ebb5e2a4 100644 --- a/problems/0654.最大二叉树.md +++ b/problems/0654.最大二叉树.md @@ -40,7 +40,7 @@ * 确定递归函数的参数和返回值 -参数就是传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。 +参数传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。 代码如下: @@ -309,30 +309,24 @@ class Solution: ```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ func constructMaximumBinaryTree(nums []int) *TreeNode { - if len(nums)<1{return nil} - //首选找到最大值 - index:=findMax(nums) - //其次构造二叉树 - root:=&TreeNode{ + if len(nums) == 0 { + return nil + } + // 找到最大值 + index := findMax(nums) + // 构造二叉树 + root := &TreeNode { Val: nums[index], - Left:constructMaximumBinaryTree(nums[:index]),//左半边 - Right:constructMaximumBinaryTree(nums[index+1:]),//右半边 + Left: constructMaximumBinaryTree(nums[:index]), //左半边 + Right: constructMaximumBinaryTree(nums[index+1:]),//右半边 } return root } -func findMax(nums []int) (index int){ - for i:=0;inums[index]{ - index=i +func findMax(nums []int) (index int) { + for i, v := range nums { + if nums[index] < v { + index = i } } return From b81abd3d6b444e256e6ed3b4f19e650f131f6732 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 11:44:01 +0800 Subject: [PATCH 02/13] =?UTF-8?q?update=200617.=E5=90=88=E5=B9=B6=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=A0=91:=20=E4=BC=98=E5=8C=96=20go=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0617.合并二叉树.md | 64 +++++++------------------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/problems/0617.合并二叉树.md b/problems/0617.合并二叉树.md index db2d3762..58701b7d 100644 --- a/problems/0617.合并二叉树.md +++ b/problems/0617.合并二叉树.md @@ -46,7 +46,7 @@ 1. **确定递归函数的参数和返回值:** -首先那么要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。 +首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。 代码如下: @@ -56,7 +56,7 @@ TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { 2. **确定终止条件:** -因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了啊(如果t2也为NULL也无所谓,合并之后就是NULL)。 +因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。 反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。 @@ -70,7 +70,7 @@ if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1 3. **确定单层递归的逻辑:** -单层递归的逻辑就比较好些了,这里我们用重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。 +单层递归的逻辑就比较好写了,这里我们重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。 那么单层递归中,就要把两棵树的元素加到一起。 ``` @@ -144,7 +144,7 @@ public: **但是前序遍历是最好理解的,我建议大家用前序遍历来做就OK。** -如上的方法修改了t1的结构,当然也可以不修改t1和t2的结构,重新定一个树。 +如上的方法修改了t1的结构,当然也可以不修改t1和t2的结构,重新定义一个树。 不修改输入树的结构,前序遍历,代码如下: @@ -214,7 +214,7 @@ public: ## 拓展 -当然也可以秀一波指针的操作,这是我写的野路子,大家就随便看看就行了,以防带跑遍了。 +当然也可以秀一波指针的操作,这是我写的野路子,大家就随便看看就行了,以防带跑偏了。 如下代码中,想要更改二叉树的值,应该传入指向指针的指针。 @@ -252,7 +252,7 @@ public: 迭代法中,一般一起操作两个树都是使用队列模拟类似层序遍历,同时处理两个树的节点,这种方式最好理解,如果用模拟递归的思路的话,要复杂一些。 -最后拓展中,我给了一个操作指针的野路子,大家随便看看就行了,如果学习C++的话,可以在去研究研究。 +最后拓展中,我给了一个操作指针的野路子,大家随便看看就行了,如果学习C++的话,可以再去研究研究。 ## 其他语言版本 @@ -417,43 +417,7 @@ class Solution: ### Go ```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ - //前序遍历(递归遍历,跟105 106差不多的思路) -func mergeTrees(t1 *TreeNode, t2 *TreeNode) *TreeNode { - var value int - var nullNode *TreeNode//空node,便于遍历 - nullNode=&TreeNode{ - Val:0, - Left:nil, - Right:nil} - switch { - case t1==nil&&t2==nil: return nil//终止条件 - default : //如果其中一个节点为空,则将该节点置为nullNode,方便下次遍历 - if t1==nil{ - value=t2.Val - t1=nullNode - }else if t2==nil{ - value=t1.Val - t2=nullNode - }else { - value=t1.Val+t2.Val - } - } - root:=&TreeNode{//构造新的二叉树 - Val: value, - Left: mergeTrees(t1.Left,t2.Left), - Right: mergeTrees(t1.Right,t2.Right)} - return root -} - -// 前序遍历简洁版 +// 前序遍历 func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode { if root1 == nil { return root2 @@ -479,28 +443,28 @@ func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode { queue = append(queue,root1) queue = append(queue,root2) - for size:=len(queue);size>0;size=len(queue){ + for size := len(queue); size>0; size=len(queue) { node1 := queue[0] queue = queue[1:] node2 := queue[0] queue = queue[1:] node1.Val += node2.Val // 左子树都不为空 - if node1.Left != nil && node2.Left != nil{ + if node1.Left != nil && node2.Left != nil { queue = append(queue,node1.Left) queue = append(queue,node2.Left) } // 右子树都不为空 - if node1.Right !=nil && node2.Right !=nil{ - queue = append(queue,node1.Right) - queue = append(queue,node2.Right) + if node1.Right !=nil && node2.Right !=nil { + queue = append(queue, node1.Right) + queue = append(queue, node2.Right) } // 树 1 的左子树为 nil,直接接上树 2 的左子树 - if node1.Left == nil{ + if node1.Left == nil { node1.Left = node2.Left } // 树 1 的右子树为 nil,直接接上树 2 的右子树 - if node1.Right == nil{ + if node1.Right == nil { node1.Right = node2.Right } } From a85036e81126de1b026772ef803776a56540946c Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 12:24:34 +0800 Subject: [PATCH 03/13] =?UTF-8?q?update=200700.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E6=90=9C=E7=B4=A2:=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20go=20=E7=9A=84=E8=BF=AD=E4=BB=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0700.二叉搜索树中的搜索.md | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/problems/0700.二叉搜索树中的搜索.md b/problems/0700.二叉搜索树中的搜索.md index 2ee2bdb0..f40f778a 100644 --- a/problems/0700.二叉搜索树中的搜索.md +++ b/problems/0700.二叉搜索树中的搜索.md @@ -24,7 +24,7 @@ ## 思路 -之前我们讲了都是普通二叉树,那么接下来看看二叉搜索树。 +之前我们讲的都是普通二叉树,那么接下来看看二叉搜索树。 在[关于二叉树,你该了解这些!](https://programmercarl.com/二叉树理论基础.html)中,我们已经讲过了二叉搜索树。 @@ -269,13 +269,13 @@ class Solution: ```go //递归法 func searchBST(root *TreeNode, val int) *TreeNode { - if root==nil||root.Val==val{ + if root == nil || root.Val == val { return root } - if root.Val>val{ - return searchBST(root.Left,val) + if root.Val > val { + return searchBST(root.Left, val) } - return searchBST(root.Right,val) + return searchBST(root.Right, val) } ``` @@ -284,13 +284,13 @@ func searchBST(root *TreeNode, val int) *TreeNode { ```go //迭代法 func searchBST(root *TreeNode, val int) *TreeNode { - for root!=nil{ - if root.Val>val{ - root=root.Left - }else if root.Val val { + root = root.Left + } else if root.Val < val { + root = root.Right + } else { + return root } } return nil From d32e8f54c8803c475ab403fc1fa918b7e74b2a8e Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 13:52:36 +0800 Subject: [PATCH 04/13] =?UTF-8?q?update=200098.=E9=AA=8C=E8=AF=81=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91:=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0098.验证二叉搜索树.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index bb38ae35..db9c28ad 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -437,8 +437,6 @@ class Solution: ## Go ```Go -import "math" - func isValidBST(root *TreeNode) bool { // 二叉搜索树也可以是空树 if root == nil { From a4d7ed61422dfef71149443eb84d3a8cb074a1b6 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 14:27:21 +0800 Subject: [PATCH 05/13] =?UTF-8?q?update=200530.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E7=9A=84=E6=9C=80=E5=B0=8F=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E5=B7=AE:=20=E5=88=A0=E9=99=A4=20go=20=E5=86=97=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0530.二叉搜索树的最小绝对差.md | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/problems/0530.二叉搜索树的最小绝对差.md b/problems/0530.二叉搜索树的最小绝对差.md index ad4f46d8..699afcf7 100644 --- a/problems/0530.二叉搜索树的最小绝对差.md +++ b/problems/0530.二叉搜索树的最小绝对差.md @@ -248,28 +248,6 @@ class Solution: ## Go: 中序遍历,然后计算最小差值 - -```go -func getMinimumDifference(root *TreeNode) int { - var res []int - findMIn(root,&res) - min:=1000000//一个比较大的值 - for i:=1;i Date: Sun, 4 Dec 2022 15:31:13 +0800 Subject: [PATCH 06/13] =?UTF-8?q?update=200501.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E4=BC=97=E6=95=B0:=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20java=EF=BC=8Cgo=20=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0501.二叉搜索树中的众数.md | 45 ++------------------ 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/problems/0501.二叉搜索树中的众数.md b/problems/0501.二叉搜索树中的众数.md index 3c6362bf..f016ee58 100644 --- a/problems/0501.二叉搜索树中的众数.md +++ b/problems/0501.二叉搜索树中的众数.md @@ -54,7 +54,7 @@ 1. 这个树都遍历了,用map统计频率 -至于用前中后序那种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行,层序遍历都没毛病! +至于用前中后序哪种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行,层序遍历都没毛病! 这里采用前序遍历,代码如下: @@ -354,7 +354,7 @@ public: ```java class Solution { - public int[] findMode(FindModeInBinarySearchTree.TreeNode root) { + public int[] findMode(TreeNode root) { Map map = new HashMap<>(); List list = new ArrayList<>(); if (root == null) return list.stream().mapToInt(Integer::intValue).toArray(); @@ -375,7 +375,7 @@ class Solution { return list.stream().mapToInt(Integer::intValue).toArray(); } - void searchBST(FindModeInBinarySearchTree.TreeNode curr, Map map) { + void searchBST(TreeNode curr, Map map) { if (curr == null) return; map.put(curr.val, map.getOrDefault(curr.val, 0) + 1); searchBST(curr.left, map); @@ -556,46 +556,7 @@ class Solution: ``` ## Go -暴力法(非BSL) - -```go -func findMode(root *TreeNode) []int { - var history map[int]int - var maxValue int - var maxIndex int - var result []int - history=make(map[int]int) - traversal(root,history) - for k,value:=range history{ - if value>maxValue{ - maxValue=value - maxIndex=k - } - } - for k,value:=range history{ - if value==history[maxIndex]{ - result=append(result,k) - } - } - return result -} -func traversal(root *TreeNode,history map[int]int){ - if root.Left!=nil{ - traversal(root.Left,history) - } - if value,ok:=history[root.Val];ok{ - history[root.Val]=value+1 - }else{ - history[root.Val]=1 - } - if root.Right!=nil{ - traversal(root.Right,history) - } -} -``` - 计数法,不使用额外空间,利用二叉树性质,中序遍历 - ```go func findMode(root *TreeNode) []int { res := make([]int, 0) From c5fa95ebffe0cbc200166a6eb914702d398be659 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 22:55:45 +0800 Subject: [PATCH 07/13] =?UTF-8?q?update=200236.=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E8=BF=91=E5=85=AC=E5=85=B1=E7=A5=96=E5=85=88?= =?UTF-8?q?=EF=BC=9A=E4=BF=AE=E6=94=B9=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0236.二叉树的最近公共祖先.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md index a34e8c21..bf2007b5 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -48,7 +48,7 @@ 后序遍历(左右中)就是天然的回溯过程,可以根据左右子树的返回值,来处理中节点的逻辑。 -接下来就看如何判断一个节点是节点q和节点p的公共公共祖先呢。 +接下来就看如何判断一个节点是节点q和节点p的公共祖先呢。 **首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。** 即情况一: @@ -66,9 +66,9 @@ 其实情况一 和 情况二 代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。 -因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本省就是 公共祖先的情况。 +因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本身就是 公共祖先的情况。 -这一点是很多录友容易忽略的,在下面的代码讲解中,可以在去体会。 +这一点是很多录友容易忽略的,在下面的代码讲解中,可以再去体会。 递归三部曲: @@ -86,9 +86,9 @@ TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) * 确定终止条件 -遇到空的话,然后然后空,因为树都是空了,所以返回空。 +遇到空的话,因为树都是空了,所以返回空。 -那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,那么中节点处理逻辑,后下面讲解。 +那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,那么中节点的处理逻辑,下面讲解。 代码如下: @@ -167,7 +167,7 @@ TreeNode* right = lowestCommonAncestor(root->right, p, q); 图中节点10的左子树返回null,右子树返回目标值7,那么此时节点10的处理逻辑就是把右子树的返回值(最近公共祖先7)返回上去! -这里点也很重要,可能刷过这道题目的同学,都不清楚结果究竟是如何从底层一层一层传到头结点的。 +这里也很重要,可能刷过这道题目的同学,都不清楚结果究竟是如何从底层一层一层传到头结点的。 那么如果left和right都为空,则返回left或者right都是可以的,也就是返回空。 @@ -231,7 +231,7 @@ public: **那么我给大家归纳如下三点**: -1. 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从低向上的遍历方式。 +1. 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。 2. 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。 @@ -332,16 +332,16 @@ var lowestCommonAncestor = function(root, p, q) { // 1. 确定递归的函数 const travelTree = function(root,p,q) { // 2. 确定递归终止条件 - if(root === null || root === p||root === q) { + if(root === null || root === p || root === q) { return root; } // 3. 确定递归单层逻辑 let left = travelTree(root.left,p,q); let right = travelTree(root.right,p,q); - if(left !== null&&right !== null) { + if(left !== null && right !== null) { return root; } - if(left ===null) { + if(left === null) { return right; } return left; From 1287679e8eedc2c49b5e61946a15445e345b4cf4 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Sun, 4 Dec 2022 23:10:10 +0800 Subject: [PATCH 08/13] =?UTF-8?q?update=200235.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E7=9A=84=E6=9C=80=E8=BF=91=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E7=A5=96=E5=85=88:=20=E6=9B=BF=E6=8D=A2=20go=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...35.二叉搜索树的最近公共祖先.md | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index c90b3d8c..391d1cfb 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -303,14 +303,22 @@ class Solution: 递归法: ```go -//利用BSL的性质(前序遍历有序) func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { - if root==nil{return nil} - if root.Val>p.Val&&root.Val>q.Val{//当前节点的值大于给定的值,则说明满足条件的在左边 - return lowestCommonAncestor(root.Left,p,q) - }else if root.Val p.Val && root.Val > q.Val { + root = root.Left + } + if root.Val < p.Val && root.Val < q.Val { + root = root.Right + } + if (root.Val - p.Val) * (root.Val - q.Val) <= 0 { + return root + } + } + return root } ``` @@ -326,11 +334,11 @@ var lowestCommonAncestor = function(root, p, q) { if(root === null) { return root; } - if(root.val>p.val&&root.val>q.val) { + if(root.val > p.val && root.val > q.val) { // 向左子树查询 return root.left = lowestCommonAncestor(root.left,p,q); } - if(root.valp.val&&root.val>q.val) { + if(root.val > p.val && root.val > q.val) { root = root.left; - }else if(root.val Date: Sun, 4 Dec 2022 23:58:10 +0800 Subject: [PATCH 09/13] =?UTF-8?q?update=200701.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E6=8F=92=E5=85=A5=E6=93=8D?= =?UTF-8?q?=E4=BD=9C:=20=E4=BF=AE=E6=94=B9=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0701.二叉搜索树中的插入操作.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md index 2e899e22..432413b6 100644 --- a/problems/0701.二叉搜索树中的插入操作.md +++ b/problems/0701.二叉搜索树中的插入操作.md @@ -24,7 +24,7 @@ # 思路 -其实这道题目其实是一道简单题目,**但是题目中的提示:有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人**,瞬间感觉题目复杂了很多。 +这道题目其实是一道简单题目,**但是题目中的提示:有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人**,瞬间感觉题目复杂了很多。 其实**可以不考虑题目中提示所说的改变树的结构的插入方式。** @@ -157,7 +157,7 @@ public: 我之所以举这个例子,是想说明通过递归函数的返回值完成父子节点的赋值是可以带来便利的。 -**网上千变一律的代码,可能会误导大家认为通过递归函数返回节点 这样的写法是天经地义,其实这里是有优化的!** +**网上千篇一律的代码,可能会误导大家认为通过递归函数返回节点 这样的写法是天经地义,其实这里是有优化的!** ## 迭代 @@ -197,7 +197,7 @@ public: 首先在二叉搜索树中的插入操作,大家不用恐惧其重构搜索树,其实根本不用重构。 -然后在递归中,我们重点讲了如果通过递归函数的返回值完成新加入节点和其父节点的赋值操作,并强调了搜索树的有序性。 +然后在递归中,我们重点讲了如何通过递归函数的返回值完成新加入节点和其父节点的赋值操作,并强调了搜索树的有序性。 最后依然给出了迭代的方法,迭代的方法就需要记录当前遍历节点的父节点了,这个和没有返回值的递归函数实现的代码逻辑是一样的。 From b93d9f6d89406cf2980cf94cfe313d7463d04d9e Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Mon, 5 Dec 2022 10:19:20 +0800 Subject: [PATCH 10/13] =?UTF-8?q?update=200450.=E5=88=A0=E9=99=A4=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E8=8A=82?= =?UTF-8?q?=E7=82=B9:=20=E4=BF=AE=E6=94=B9=E9=94=99=E5=AD=97=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20go=20=E4=BB=A3=E7=A0=81=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0450.删除二叉搜索树中的节点.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index d178596e..0b4048d5 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -25,7 +25,7 @@ # 思路 -搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑,做好心里准备。 +搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑,做好心理准备。 ## 递归 @@ -33,7 +33,7 @@ * 确定递归函数参数以及返回值 -说道递归函数的返回值,在[二叉树:搜索树中的插入操作](https://programmercarl.com/0701.二叉搜索树中的插入操作.html)中通过递归返回值来加入新节点, 这里也可以通过递归返回值删除节点。 +说到递归函数的返回值,在[二叉树:搜索树中的插入操作](https://programmercarl.com/0701.二叉搜索树中的插入操作.html)中通过递归返回值来加入新节点, 这里也可以通过递归返回值删除节点。 代码如下: @@ -66,7 +66,7 @@ if (root == nullptr) return root; ![450.删除二叉搜索树中的节点](https://tva1.sinaimg.cn/large/008eGmZEly1gnbj3k596mg30dq0aigyz.gif) -动画中棵二叉搜索树中,删除元素7, 那么删除节点(元素7)的左孩子就是5,删除节点(元素7)的右子树的最左面节点是元素8。 +动画中的二叉搜索树中,删除元素7, 那么删除节点(元素7)的左孩子就是5,删除节点(元素7)的右子树的最左面节点是元素8。 将删除节点(元素7)的左孩子放到删除节点(元素7)的右子树的最左面节点(元素8)的左孩子上,就是把5为根节点的子树移到了8的左孩子的位置。 @@ -251,7 +251,7 @@ public: **这里最关键的逻辑就是第五种情况(删除一个左右孩子都不为空的节点),这种情况一定要想清楚**。 -而且就算想清楚了,对应的代码也未必可以写出来,所以**这道题目即考察思维逻辑,也考察代码能力**。 +而且就算想清楚了,对应的代码也未必可以写出来,所以**这道题目既考察思维逻辑,也考察代码能力**。 递归中我给出了两种写法,推荐大家学会第一种(利用搜索树的特性)就可以了,第二种递归写法其实是比较绕的。 @@ -390,39 +390,39 @@ class Solution: ```Go // 递归版本 func deleteNode(root *TreeNode, key int) *TreeNode { - if root==nil{ + if root == nil { return nil } - if keyroot.Val{ - root.Right=deleteNode(root.Right,key) + if key > root.Val { + root.Right = deleteNode(root.Right, key) return root } - if root.Right==nil{ + if root.Right == nil { return root.Left } - if root.Left==nil{ + if root.Left == nil{ return root.Right } - minnode:=root.Right - for minnode.Left!=nil{ - minnode=minnode.Left + minnode := root.Right + for minnode.Left != nil { + minnode = minnode.Left } - root.Val=minnode.Val - root.Right=deleteNode1(root.Right) + root.Val = minnode.Val + root.Right = deleteNode1(root.Right) return root } -func deleteNode1(root *TreeNode)*TreeNode{ - if root.Left==nil{ - pRight:=root.Right - root.Right=nil +func deleteNode1(root *TreeNode)*TreeNode { + if root.Left == nil { + pRight := root.Right + root.Right = nil return pRight } - root.Left=deleteNode1(root.Left) + root.Left = deleteNode1(root.Left) return root } // 迭代版本 From 10302b0a143d0b0c736466da197c6dba8ff76c07 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Mon, 5 Dec 2022 14:33:48 +0800 Subject: [PATCH 11/13] =?UTF-8?q?update=200669.=E4=BF=AE=E5=89=AA=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91:=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0669.修剪二叉搜索树.md | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index 98af3c26..c2d7b79b 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -59,7 +59,7 @@ public: ![669.修剪二叉搜索树1](https://img-blog.csdnimg.cn/20210204155327203.png) -理解了最关键部分了我们在递归三部曲: +理解了最关键部分了我们再递归三部曲: * 确定递归函数的参数以及返回值 @@ -179,7 +179,7 @@ public: }; ``` -只看代码,其实不太好理解节点是符合移除的,这一块大家可以自己在模拟模拟! +只看代码,其实不太好理解节点是如何移除的,这一块大家可以自己再模拟模拟! ## 迭代法 @@ -301,19 +301,19 @@ class Solution: // 递归 func trimBST(root *TreeNode, low int, high int) *TreeNode { - if root==nil{ + if root == nil { return nil } - if root.Valhigh{//如果该节点的值大于最大值,则该节点更换为该节点的左节点值,继续遍历 - left:=trimBST(root.Left,low,high) + if root.Val > high { //如果该节点的值大于最大值,则该节点更换为该节点的左节点值,继续遍历 + left := trimBST(root.Left, low, high) return left } - root.Left=trimBST(root.Left,low,high) - root.Right=trimBST(root.Right,low,high) + root.Left = trimBST(root.Left, low, high) + root.Right = trimBST(root.Right, low, high) return root } @@ -323,25 +323,25 @@ func trimBST(root *TreeNode, low int, high int) *TreeNode { return nil } // 处理 root,让 root 移动到[low, high] 范围内,注意是左闭右闭 - for root != nil && (root.Valhigh){ - if root.Val < low{ + for root != nil && (root.Val < low || root.Val > high) { + if root.Val < low { root = root.Right - }else{ + } else { root = root.Left } } cur := root // 此时 root 已经在[low, high] 范围内,处理左孩子元素小于 low 的情况(左节点是一定小于 root.Val,因此天然小于 high) - for cur != nil{ - for cur.Left!=nil && cur.Left.Val < low{ + for cur != nil { + for cur.Left != nil && cur.Left.Val < low { cur.Left = cur.Left.Right } cur = cur.Left } cur = root // 此时 root 已经在[low, high] 范围内,处理右孩子大于 high 的情况 - for cur != nil{ - for cur.Right!=nil && cur.Right.Val > high{ + for cur != nil { + for cur.Right != nil && cur.Right.Val > high { cur.Right = cur.Right.Left } cur = cur.Right @@ -359,24 +359,24 @@ var trimBST = function(root, low, high) { if(root === null) { return null; } - while(root !==null &&(root.valhigh)) { - if(root.val high)) { + if(root.val < low) { root = root.right; }else { root = root.left; } } let cur = root; - while(cur!==null) { - while(cur.left&&cur.left.valhigh) { + while(cur !== null) { + while(cur.right && cur.right.val > high) { cur.right = cur.right.left; } cur = cur.right; @@ -391,16 +391,16 @@ var trimBST = function (root,low,high) { if(root === null) { return null; } - if(root.valhigh) { - let left = trimBST(root.left,low,high); + if(root.val > high) { + let left = trimBST(root.left, low, high); return left; } - root.left = trimBST(root.left,low,high); - root.right = trimBST(root.right,low,high); + root.left = trimBST(root.left, low, high); + root.right = trimBST(root.right, low, high); return root; } ``` From 57c41cd67076e7969e35a7aea353bac9931763e1 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Mon, 5 Dec 2022 15:39:02 +0800 Subject: [PATCH 12/13] =?UTF-8?q?update=200108.=E5=B0=86=E6=9C=89=E5=BA=8F?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E8=BD=AC=E6=8D=A2=E4=B8=BA=E4=BA=8C=E5=8F=89?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=A0=91:=20=E4=BC=98=E5=8C=96go=20=E5=92=8C?= =?UTF-8?q?=20js=20=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...将有序数组转换为二叉搜索树.md | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/problems/0108.将有序数组转换为二叉搜索树.md b/problems/0108.将有序数组转换为二叉搜索树.md index 9318a0e2..ffb60b38 100644 --- a/problems/0108.将有序数组转换为二叉搜索树.md +++ b/problems/0108.将有序数组转换为二叉搜索树.md @@ -35,7 +35,7 @@ 因为只要给我们一个有序数组,如果强调平衡,都可以以线性结构来构造二叉搜索树。 -例如 有序数组[-10,-3,0,5,9] 可以就可以构造成这样的二叉搜索树,如图。 +例如 有序数组[-10,-3,0,5,9] 就可以构造成这样的二叉搜索树,如图。 ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20220930173553.png) @@ -147,7 +147,7 @@ public: }; ``` -**注意:在调用traversal的时候为什么传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭**。 +**注意:在调用traversal的时候传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭**。 ## 迭代法 @@ -354,10 +354,15 @@ class Solution: ```go func sortedArrayToBST(nums []int) *TreeNode { - if len(nums)==0{return nil}//终止条件,最后数组为空则可以返回 - root:=&TreeNode{nums[len(nums)/2],nil,nil}//按照BSL的特点,从中间构造节点 - root.Left=sortedArrayToBST(nums[:len(nums)/2])//数组的左边为左子树 - root.Right=sortedArrayToBST(nums[len(nums)/2+1:])//数字的右边为右子树 + if len(nums) == 0 { //终止条件,最后数组为空则可以返回 + return nil + } + idx := len(nums)/2 + root := &TreeNode{Val: nums[idx]} + + root.Left = sortedArrayToBST(nums[:idx]) + root.Right = sortedArrayToBST(nums[idx+1:]) + return root } ``` @@ -384,33 +389,33 @@ var sortedArrayToBST = function (nums) { 迭代 ```JavaScript var sortedArrayToBST = function(nums) { - if(nums.length===0){ + if(nums.length===0) { return null; } - let root=new TreeNode(0); //初始根节点 - let nodeQue=[root]; //放遍历的节点,并初始化 - let leftQue=[0]; //放左区间的下标,初始化 - let rightQue=[nums.length-1]; // 放右区间的下标 + let root = new TreeNode(0); //初始根节点 + let nodeQue = [root]; //放遍历的节点,并初始化 + let leftQue = [0]; //放左区间的下标,初始化 + let rightQue = [nums.length-1]; // 放右区间的下标 - while(nodeQue.length){ - let curNode=nodeQue.pop(); - let left=leftQue.pop(); - let right=rightQue.pop(); - let mid=left+Math.floor((right-left)/2); + while(nodeQue.length) { + let curNode = nodeQue.pop(); + let left = leftQue.pop(); + let right = rightQue.pop(); + let mid = left + Math.floor((right-left)/2); - curNode.val=nums[mid]; //将下标为mid的元素给中间节点 + curNode.val = nums[mid]; //将下标为mid的元素给中间节点 // 处理左区间 - if(left<=mid-1){ - curNode.left=new TreeNode(0); + if(left <= mid-1) { + curNode.left = new TreeNode(0); nodeQue.push(curNode.left); leftQue.push(left); rightQue.push(mid-1); } // 处理右区间 - if(right>=mid+1){ - curNode.right=new TreeNode(0); + if(right >= mid+1) { + curNode.right = new TreeNode(0); nodeQue.push(curNode.right); leftQue.push(mid+1); rightQue.push(right); From c03d5310a736f16accb2bf2e294743ac24e7d913 Mon Sep 17 00:00:00 2001 From: Yuhao Ju Date: Mon, 5 Dec 2022 19:13:43 +0800 Subject: [PATCH 13/13] =?UTF-8?q?update=200538.=E6=8A=8A=E4=BA=8C=E5=8F=89?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=A0=91=E8=BD=AC=E6=8D=A2=E4=B8=BA=E7=B4=AF?= =?UTF-8?q?=E5=8A=A0=E6=A0=91=EF=BC=9A=E6=9B=BF=E6=8D=A2=20go=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...38.把二叉搜索树转换为累加树.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/problems/0538.把二叉搜索树转换为累加树.md b/problems/0538.把二叉搜索树转换为累加树.md index 823771b1..9940e604 100644 --- a/problems/0538.把二叉搜索树转换为累加树.md +++ b/problems/0538.把二叉搜索树转换为累加树.md @@ -45,11 +45,11 @@ # 思路 -一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后在遍历其他节点累加?怎么一想这么麻烦呢。 +一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后再遍历其他节点累加?怎么一想这么麻烦呢。 然后再发现这是一棵二叉搜索树,二叉搜索树啊,这是有序的啊。 -那么有序的元素如果求累加呢? +那么有序的元素如何求累加呢? **其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。** @@ -233,23 +233,23 @@ class Solution: ## Go 弄一个sum暂存其和值 - ```go - //右中左 -func bstToGst(root *TreeNode) *TreeNode { - var sum int - RightMLeft(root,&sum) - return root -} -func RightMLeft(root *TreeNode,sum *int) *TreeNode { - if root==nil{return nil}//终止条件,遇到空节点就返回 - RightMLeft(root.Right,sum)//先遍历右边 - temp:=*sum//暂存总和值 - *sum+=root.Val//将总和值变更 - root.Val+=temp//更新节点值 - RightMLeft(root.Left,sum)//遍历左节点 +var pre int +func convertBST(root *TreeNode) *TreeNode { + pre = 0 + traversal(root) return root } + +func traversal(cur *TreeNode) { + if cur == nil { + return + } + traversal(cur.Right) + cur.Val += pre + pre = cur.Val + traversal(cur.Left) +} ``` ## JavaScript