Merge pull request #1787 from juguagua/leetcode-modify-the-code-of-the-BinaryTree

完善更新二叉树部分:从 二叉树遍历 至 对称二叉树
This commit is contained in:
程序员Carl
2022-11-30 11:59:19 +08:00
committed by GitHub
5 changed files with 404 additions and 389 deletions

View File

@ -21,7 +21,7 @@
对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了**其实我们要比较的是两个树(这两个树是根节点的左右子树)**,所以在递归遍历的过程中,也是要同时遍历两棵树。 对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了**其实我们要比较的是两个树(这两个树是根节点的左右子树)**,所以在递归遍历的过程中,也是要同时遍历两棵树。
那么如比较呢? 那么如比较呢?
比较的是两个子树的里侧和外侧的元素是否相等。如图所示: 比较的是两个子树的里侧和外侧的元素是否相等。如图所示:
@ -80,7 +80,7 @@ else if (left == NULL && right == NULL) return true;
else if (left->val != right->val) return false; // 注意这里我没有使用else else if (left->val != right->val) return false; // 注意这里我没有使用else
``` ```
注意上面最后一种情况我没有使用else而是elseif 因为我们把以上情况都排除之后,剩下的就是 左右节点都不为空,且数值相同的情况。 注意上面最后一种情况我没有使用else而是else if 因为我们把以上情况都排除之后,剩下的就是 左右节点都不为空,且数值相同的情况。
3. 确定单层递归的逻辑 3. 确定单层递归的逻辑
@ -244,7 +244,7 @@ public:
这次我们又深度剖析了一道二叉树的“简单题”大家会发现真正的把题目搞清楚其实并不简单leetcode上accept了和真正掌握了还是有距离的。 这次我们又深度剖析了一道二叉树的“简单题”大家会发现真正的把题目搞清楚其实并不简单leetcode上accept了和真正掌握了还是有距离的。
我们介绍了递归法和迭代法,递归依然通过递归三部曲来解决了这道题目,如果只看精简的代码根本看不出来递归三部曲是如解题的。 我们介绍了递归法和迭代法,递归依然通过递归三部曲来解决了这道题目,如果只看精简的代码根本看不出来递归三部曲是如解题的。
在迭代法中我们使用了队列,需要注意的是这不是层序遍历,而且仅仅通过一个容器来成对的存放我们要比较的元素,知道这一本质之后就发现,用队列,用栈,甚至用数组,都是可以的。 在迭代法中我们使用了队列,需要注意的是这不是层序遍历,而且仅仅通过一个容器来成对的存放我们要比较的元素,知道这一本质之后就发现,用队列,用栈,甚至用数组,都是可以的。
@ -259,7 +259,7 @@ public:
# 其他语言版本 # 其他语言版本
## Java Java
```Java ```Java
/** /**
@ -364,7 +364,7 @@ public:
``` ```
## Python Python
递归法: 递归法:
```python ```python
@ -464,8 +464,7 @@ class Solution:
return True return True
``` ```
## Go Go
```go ```go
/** /**
* Definition for a binary tree node. * Definition for a binary tree node.
@ -488,10 +487,12 @@ func defs(left *TreeNode, right *TreeNode) bool {
} }
return defs(left.Left, right.Right) && defs(right.Left, left.Right); return defs(left.Left, right.Right) && defs(right.Left, left.Right);
} }
func isSymmetric(root *TreeNode) bool { func isSymmetric(root *TreeNode) bool {
return defs(root.Left, root.Right); return defs(root.Left, root.Right);
} }
// 迭代 // 迭代
func isSymmetric(root *TreeNode) bool { func isSymmetric(root *TreeNode) bool {
var queue []*TreeNode; var queue []*TreeNode;
@ -515,59 +516,60 @@ func isSymmetric(root *TreeNode) bool {
``` ```
## JavaScript JavaScript
递归判断是否为对称二叉树: 递归判断是否为对称二叉树:
```javascript ```javascript
var isSymmetric = function(root) { var isSymmetric = function(root) {
//使用递归遍历左右子树 递归三部曲 // 使用递归遍历左右子树 递归三部曲
// 1. 确定递归的参数 root.left root.right和返回值true false // 1. 确定递归的参数 root.left root.right和返回值true false
const compareNode=function(left,right){ const compareNode = function(left, right) {
//2. 确定终止条件 空的情况 // 2. 确定终止条件 空的情况
if(left===null&&right!==null||left!==null&&right===null){ if(left === null && right !== null || left !== null && right === null) {
return false; return false;
}else if(left===null&&right===null){ } else if(left === null && right === null) {
return true; return true;
}else if(left.val!==right.val){ } else if(left.val !== right.val) {
return false; return false;
} }
//3. 确定单层递归逻辑 // 3. 确定单层递归逻辑
let outSide=compareNode(left.left,right.right); let outSide = compareNode(left.left, right.right);
let inSide=compareNode(left.right,right.left); let inSide = compareNode(left.right, right.left);
return outSide&&inSide; return outSide && inSide;
} }
if(root===null){ if(root === null) {
return true; return true;
} }
return compareNode(root.left,root.right); return compareNode(root.left, root.right);
}; };
``` ```
队列实现迭代判断是否为对称二叉树: 队列实现迭代判断是否为对称二叉树:
```javascript ```javascript
var isSymmetric = function(root) { var isSymmetric = function(root) {
//迭代方法判断是否是对称二叉树 // 迭代方法判断是否是对称二叉树
//首先判断root是否为空 // 首先判断root是否为空
if(root===null){ if(root === null) {
return true; return true;
} }
let queue=[]; let queue = [];
queue.push(root.left); queue.push(root.left);
queue.push(root.right); queue.push(root.right);
while(queue.length){ while(queue.length) {
let leftNode=queue.shift();//左节点 let leftNode = queue.shift(); //左节点
let rightNode=queue.shift();//右节点 let rightNode = queue.shift(); //右节点
if(leftNode===null&&rightNode===null){ if(leftNode === null && rightNode === null) {
continue; continue;
} }
if(leftNode===null||rightNode===null||leftNode.val!==rightNode.val){ if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val) {
return false; return false;
} }
queue.push(leftNode.left);//左节点左孩子入队 queue.push(leftNode.left); //左节点左孩子入队
queue.push(rightNode.right);//右节点右孩子入队 queue.push(rightNode.right); //右节点右孩子入队
queue.push(leftNode.right);//左节点右孩子入队 queue.push(leftNode.right); //左节点右孩子入队
queue.push(rightNode.left);//右节点左孩子入队 queue.push(rightNode.left); //右节点左孩子入队
} }
return true; return true;
}; };
``` ```
@ -575,33 +577,34 @@ var isSymmetric = function(root) {
栈实现迭代判断是否为对称二叉树: 栈实现迭代判断是否为对称二叉树:
```javascript ```javascript
var isSymmetric = function(root) { var isSymmetric = function(root) {
//迭代方法判断是否是对称二叉树 // 迭代方法判断是否是对称二叉树
//首先判断root是否为空 // 首先判断root是否为空
if(root===null){ if(root === null) {
return true; return true;
} }
let stack=[]; let stack = [];
stack.push(root.left); stack.push(root.left);
stack.push(root.right); stack.push(root.right);
while(stack.length){ while(stack.length) {
let rightNode=stack.pop();//左节点 let rightNode = stack.pop(); //左节点
let leftNode=stack.pop();//右节点 let leftNode=stack.pop(); //右节点
if(leftNode===null&&rightNode===null){ if(leftNode === null && rightNode === null) {
continue; continue;
} }
if(leftNode===null||rightNode===null||leftNode.val!==rightNode.val){ if(leftNode === null || rightNode === null || leftNode.val !== rightNode.val) {
return false; return false;
} }
stack.push(leftNode.left);//左节点左孩子入队 stack.push(leftNode.left); //左节点左孩子入队
stack.push(rightNode.right);//右节点右孩子入队 stack.push(rightNode.right); //右节点右孩子入队
stack.push(leftNode.right);//左节点右孩子入队 stack.push(leftNode.right); //左节点右孩子入队
stack.push(rightNode.left);//右节点左孩子入队 stack.push(rightNode.left); //右节点左孩子入队
} }
return true; return true;
}; };
``` ```
## TypeScript TypeScript
> 递归法 > 递归法
@ -670,7 +673,7 @@ function isSymmetric(root: TreeNode | null): boolean {
}; };
``` ```
## Swift: Swift:
> 递归 > 递归
```swift ```swift
@ -752,7 +755,7 @@ func isSymmetric3(_ root: TreeNode?) -> Bool {
} }
``` ```
## Scala Scala
> 递归: > 递归:
```scala ```scala

View File

@ -47,7 +47,7 @@
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。 层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。
需要借用一个辅助数据结构即队列来实现,**队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。** 需要借用一个辅助数据结构即队列来实现,**队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。**
**而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。** **而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。**
@ -106,50 +106,6 @@ public:
}; };
``` ```
python3代码
```python
class Solution:
"""二叉树层序遍历迭代解法"""
def levelOrder(self, root: TreeNode) -> List[List[int]]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
size = len(que)
result = []
for _ in range(size):
cur = que.popleft()
result.append(cur.val)
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
results.append(result)
return results
```
```python
# 递归法
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
def helper(root, depth):
if not root: return []
if len(res) == depth: res.append([]) # start the current depth
res[depth].append(root.val) # fulfil the current depth
if root.left: helper(root.left, depth + 1) # process child nodes for the next depth
if root.right: helper(root.right, depth + 1)
helper(root, 0)
return res
```
java: java:
```Java ```Java
@ -206,6 +162,51 @@ class Solution {
} }
``` ```
python3代码
```python
class Solution:
"""二叉树层序遍历迭代解法"""
def levelOrder(self, root: TreeNode) -> List[List[int]]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
size = len(que)
result = []
for _ in range(size):
cur = que.popleft()
result.append(cur.val)
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
results.append(result)
return results
```
```python
# 递归法
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
def helper(root, depth):
if not root: return []
if len(res) == depth: res.append([]) # start the current depth
res[depth].append(root.val) # fulfil the current depth
if root.left: helper(root.left, depth + 1) # process child nodes for the next depth
if root.right: helper(root.right, depth + 1)
helper(root, 0)
return res
```
go: go:
```go ```go
@ -243,28 +244,31 @@ func levelOrder(root *TreeNode) [][]int {
102. 二叉树的层序遍历 102. 二叉树的层序遍历
*/ */
func levelOrder(root *TreeNode) [][]int { func levelOrder(root *TreeNode) [][]int {
res:=[][]int{} res := [][]int{}
if root==nil{//防止为空 if root == nil{//防止为空
return res return res
} }
queue:=list.New() queue := list.New()
queue.PushBack(root) queue.PushBack(root)
var tmpArr []int var tmpArr []int
for queue.Len()>0 {
length:=queue.Len()//保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数) for queue.Len() > 0 {
for i:=0;i<length;i++{ length := queue.Len() //保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
node:=queue.Remove(queue.Front()).(*TreeNode)//出队列 for i := 0; i < length; i++ {
if node.Left!=nil{ node := queue.Remove(queue.Front()).(*TreeNode) //出队列
if node.Left != nil {
queue.PushBack(node.Left) queue.PushBack(node.Left)
} }
if node.Right!=nil{ if node.Right != nil {
queue.PushBack(node.Right) queue.PushBack(node.Right)
} }
tmpArr=append(tmpArr,node.Val)//将值加入本层切片中 tmpArr = append(tmpArr, node.Val) //将值加入本层切片中
} }
res=append(res,tmpArr)//放入结果集 res = append(res, tmpArr) //放入结果集
tmpArr=[]int{}//清空层的数据 tmpArr = []int{} //清空层的数据
} }
return res return res
} }
``` ```
@ -274,22 +278,22 @@ javascript代码
```javascript ```javascript
var levelOrder = function(root) { var levelOrder = function(root) {
//二叉树的层序遍历 //二叉树的层序遍历
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
if(root===null){ if(root === null) {
return res; return res;
} }
while(queue.length!==0){ while(queue.length !== 0) {
// 记录当前层级节点数 // 记录当前层级节点数
let length=queue.length; let length = queue.length;
//存放每一层的节点 //存放每一层的节点
let curLevel=[]; let curLevel = [];
for(let i=0;i<length;i++){ for(let i = 0;i < length; i++) {
let node=queue.shift(); let node = queue.shift();
curLevel.push(node.val); curLevel.push(node.val);
// 存放当前层下一层的节点 // 存放当前层下一层的节点
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
//把每一层的结果放到结果数组 //把每一层的结果放到结果数组
res.push(curLevel); res.push(curLevel);
@ -535,31 +539,34 @@ go:
107. 二叉树的层序遍历 II 107. 二叉树的层序遍历 II
*/ */
func levelOrderBottom(root *TreeNode) [][]int { func levelOrderBottom(root *TreeNode) [][]int {
queue:=list.New() queue := list.New()
res:=[][]int{} res := [][]int{}
if root==nil{ if root == nil{
return res return res
} }
queue.PushBack(root) queue.PushBack(root)
for queue.Len()>0{
length:=queue.Len() for queue.Len() > 0 {
tmp:=[]int{} length := queue.Len()
for i:=0;i<length;i++{ tmp := []int{}
node:=queue.Remove(queue.Front()).(*TreeNode) for i := 0; i < length; i++ {
if node.Left!=nil{ node := queue.Remove(queue.Front()).(*TreeNode)
if node.Left != nil {
queue.PushBack(node.Left) queue.PushBack(node.Left)
} }
if node.Right!=nil{ if node.Right != nil {
queue.PushBack(node.Right) queue.PushBack(node.Right)
} }
tmp=append(tmp,node.Val) tmp = append(tmp, node.Val)
} }
res=append(res,tmp) res=append(res, tmp)
} }
//反转结果集 //反转结果集
for i:=0;i<len(res)/2;i++{ for i:=0; i<len(res)/2; i++ {
res[i],res[len(res)-i-1]=res[len(res)-i-1],res[i] res[i], res[len(res)-i-1] = res[len(res)-i-1], res[i]
} }
return res return res
} }
``` ```
@ -568,20 +575,20 @@ javascript代码
```javascript ```javascript
var levelOrderBottom = function(root) { var levelOrderBottom = function(root) {
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
while(queue.length&&root!==null){ while(queue.length && root!==null) {
// 存放当前层级节点数组 // 存放当前层级节点数组
let curLevel=[]; let curLevel = [];
// 计算当前层级节点数量 // 计算当前层级节点数量
let length=queue.length; let length = queue.length;
while(length--){ while(length--) {
let node=queue.shift(); let node = queue.shift();
// 把当前层节点存入curLevel数组 // 把当前层节点存入curLevel数组
curLevel.push(node.val); curLevel.push(node.val);
// 把下一层级的左右节点存入queue队列 // 把下一层级的左右节点存入queue队列
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
// 从数组前头插入值,避免最后反转数组,减少运算时间 // 从数组前头插入值,避免最后反转数组,减少运算时间
res.unshift(curLevel); res.unshift(curLevel);
@ -852,21 +859,23 @@ javascript代码:
```javascript ```javascript
var rightSideView = function(root) { var rightSideView = function(root) {
//二叉树右视图 只需要把每一层最后一个节点存储到res数组 //二叉树右视图 只需要把每一层最后一个节点存储到res数组
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
while(queue.length&&root!==null){
while(queue.length && root!==null) {
// 记录当前层级节点个数 // 记录当前层级节点个数
let length=queue.length; let length = queue.length;
while(length--){ while(length--) {
let node=queue.shift(); let node = queue.shift();
//length长度为0的时候表明到了层级最后一个节点 // length长度为0的时候表明到了层级最后一个节点
if(!length){ if(!length) {
res.push(node.val); res.push(node.val);
} }
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
} }
return res; return res;
}; };
``` ```
@ -1129,22 +1138,24 @@ javascript代码
```javascript ```javascript
var averageOfLevels = function(root) { var averageOfLevels = function(root) {
//层级平均值 //层级平均值
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
while(queue.length&&root!==null){
while(queue.length && root!==null) {
//每一层节点个数 //每一层节点个数
let length=queue.length; let length = queue.length;
//sum记录每一层的和 //sum记录每一层的和
let sum=0; let sum = 0;
for(let i=0;i<length;i++){ for(let i=0; i < length; i++) {
let node=queue.shift(); let node = queue.shift();
sum+=node.val; sum += node.val;
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
//每一层的平均值存入数组res //每一层的平均值存入数组res
res.push(sum/length); res.push(sum/length);
} }
return res; return res;
}; };
``` ```
@ -1405,24 +1416,25 @@ go:
*/ */
func levelOrder(root *Node) [][]int { func levelOrder(root *Node) [][]int {
queue:=list.New() queue := list.New()
res:=[][]int{}//结果集 res := [][]int{} //结果集
if root==nil{ if root == nil{
return res return res
} }
queue.PushBack(root) queue.PushBack(root)
for queue.Len()>0{ for queue.Len() > 0 {
length:=queue.Len()//记录当前层的数量 length := queue.Len() //记录当前层的数量
var tmp []int var tmp []int
for T:=0;T<length;T++{//该层的每个元素:一添加到该层的结果集中;二找到该元素的下层元素加入到队列中,方便下次使用 for T := 0; T < length; T++ { //该层的每个元素:一添加到该层的结果集中;二找到该元素的下层元素加入到队列中,方便下次使用
myNode:=queue.Remove(queue.Front()).(*Node) myNode := queue.Remove(queue.Front()).(*Node)
tmp=append(tmp,myNode.Val) tmp = append(tmp, myNode.Val)
for i:=0;i<len(myNode.Children);i++{ for i := 0; i < len(myNode.Children); i++ {
queue.PushBack(myNode.Children[i]) queue.PushBack(myNode.Children[i])
} }
} }
res=append(res,tmp) res = append(res, tmp)
} }
return res return res
} }
``` ```
@ -1432,23 +1444,26 @@ JavaScript代码
```JavaScript ```JavaScript
var levelOrder = function(root) { var levelOrder = function(root) {
//每一层可能有2个以上,所以不再使用node.left node.right //每一层可能有2个以上,所以不再使用node.left node.right
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
while(queue.length&&root!==null){
while(queue.length && root!==null) {
//记录每一层节点个数还是和二叉树一致 //记录每一层节点个数还是和二叉树一致
let length=queue.length; let length = queue.length;
//存放每层节点 也和二叉树一致 //存放每层节点 也和二叉树一致
let curLevel=[]; let curLevel = [];
while(length--){ while(length--) {
let node = queue.shift(); let node = queue.shift();
curLevel.push(node.val); curLevel.push(node.val);
//这里不再是 ndoe.left node.right 而是循坏node.children //这里不再是 ndoe.left node.right 而是循坏node.children
for(let item of node.children){ for(let item of node.children){
item&&queue.push(item); item && queue.push(item);
} }
} }
res.push(curLevel); res.push(curLevel);
} }
return res; return res;
}; };
``` ```
@ -1708,21 +1723,23 @@ javascript代码
```javascript ```javascript
var largestValues = function(root) { var largestValues = function(root) {
//使用层序遍历 //使用层序遍历
let res=[],queue=[]; let res = [], queue = [];
queue.push(root); queue.push(root);
while(root!==null&&queue.length){
while(root !== null && queue.length) {
//设置max初始值就是队列的第一个元素 //设置max初始值就是队列的第一个元素
let max=queue[0].val; let max = queue[0].val;
let length=queue.length; let length = queue.length;
while(length--){ while(length--) {
let node = queue.shift(); let node = queue.shift();
max=max>node.val?max:node.val; max = max > node.val ? max : node.val;
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
//把每一层的最大值放到res数组 //把每一层的最大值放到res数组
res.push(max); res.push(max);
} }
return res; return res;
}; };
``` ```
@ -1964,66 +1981,6 @@ class Solution:
first = first.left # 从本层扩展到下一层 first = first.left # 从本层扩展到下一层
return root return root
``` ```
JavaScript:
```javascript
/**
* // Definition for a Node.
* function Node(val, left, right, next) {
* this.val = val === undefined ? null : val;
* this.left = left === undefined ? null : left;
* this.right = right === undefined ? null : right;
* this.next = next === undefined ? null : next;
* };
*/
/**
* @param {Node} root
* @return {Node}
*/
var connect = function(root) {
if (root === null) return root;
let queue = [root];
while (queue.length) {
let n = queue.length;
for (let i=0; i<n; i++) {
let node = queue.shift();
if (i < n-1) {
node.next = queue[0];
}
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return root;
};
```
TypeScript:
```typescript
function connect(root: Node | null): Node | null {
let helperQueue: Node[] = [];
let preNode: Node, curNode: Node;
if (root !== null) helperQueue.push(root);
while (helperQueue.length > 0) {
for (let i = 0, length = helperQueue.length; i < length; i++) {
if (i === 0) {
preNode = helperQueue.shift()!;
} else {
curNode = helperQueue.shift()!;
preNode.next = curNode;
preNode = curNode;
}
if (preNode.left) helperQueue.push(preNode.left);
if (preNode.right) helperQueue.push(preNode.right);
}
preNode.next = null;
}
return root;
};
```
go: go:
```GO ```GO
@ -2064,6 +2021,66 @@ func connect(root *Node) *Node {
``` ```
JavaScript:
```javascript
/**
* // Definition for a Node.
* function Node(val, left, right, next) {
* this.val = val === undefined ? null : val;
* this.left = left === undefined ? null : left;
* this.right = right === undefined ? null : right;
* this.next = next === undefined ? null : next;
* };
*/
/**
* @param {Node} root
* @return {Node}
*/
var connect = function(root) {
if (root === null) return root;
let queue = [root];
while (queue.length) {
let n = queue.length;
for (let i = 0; i < n; i++) {
let node = queue.shift();
if (i < n-1) {
node.next = queue[0];
}
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return root;
};
```
TypeScript:
```typescript
function connect(root: Node | null): Node | null {
let helperQueue: Node[] = [];
let preNode: Node, curNode: Node;
if (root !== null) helperQueue.push(root);
while (helperQueue.length > 0) {
for (let i = 0, length = helperQueue.length; i < length; i++) {
if (i === 0) {
preNode = helperQueue.shift()!;
} else {
curNode = helperQueue.shift()!;
preNode.next = curNode;
preNode = curNode;
}
if (preNode.left) helperQueue.push(preNode.left);
if (preNode.right) helperQueue.push(preNode.right);
}
preNode.next = null;
}
return root;
};
```
Swift Swift
```swift ```swift
@ -2226,6 +2243,45 @@ class Solution:
return root return root
``` ```
go:
```GO
/**
116. 填充每个节点的下一个右侧节点指针
117. 填充每个节点的下一个右侧节点指针 II
*/
func connect(root *Node) *Node {
if root == nil { //防止为空
return root
}
queue := list.New()
queue.PushBack(root)
tmpArr := make([]*Node, 0)
for queue.Len() > 0 {
length := queue.Len() //保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
for i := 0; i < length; i++ {
node := queue.Remove(queue.Front()).(*Node) //出队列
if node.Left != nil {
queue.PushBack(node.Left)
}
if node.Right != nil {
queue.PushBack(node.Right)
}
tmpArr = append(tmpArr, node) //将值加入本层切片中
}
if len(tmpArr) > 1 {
// 遍历每层元素,指定next
for i := 0; i < len(tmpArr)-1; i++ {
tmpArr[i].Next = tmpArr[i+1]
}
}
tmpArr = []*Node{} //清空层的数据
}
return root
}
```
JavaScript: JavaScript:
```javascript ```javascript
/** /**
@ -2284,44 +2340,6 @@ function connect(root: Node | null): Node | null {
}; };
``` ```
go:
```GO
/**
116. 填充每个节点的下一个右侧节点指针
117. 填充每个节点的下一个右侧节点指针 II
*/
func connect(root *Node) *Node {
if root == nil { //防止为空
return root
}
queue := list.New()
queue.PushBack(root)
tmpArr := make([]*Node, 0)
for queue.Len() > 0 {
length := queue.Len() //保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
for i := 0; i < length; i++ {
node := queue.Remove(queue.Front()).(*Node) //出队列
if node.Left != nil {
queue.PushBack(node.Left)
}
if node.Right != nil {
queue.PushBack(node.Right)
}
tmpArr = append(tmpArr, node) //将值加入本层切片中
}
if len(tmpArr) > 1 {
// 遍历每层元素,指定next
for i := 0; i < len(tmpArr)-1; i++ {
tmpArr[i].Next = tmpArr[i+1]
}
}
tmpArr = []*Node{} //清空层的数据
}
return root
}
```
Swift Swift
```swift ```swift
@ -2461,7 +2479,6 @@ class Solution {
} }
``` ```
Python Python
```python 3 ```python 3
class Solution: class Solution:
@ -2498,20 +2515,20 @@ Go
* } * }
*/ */
func maxDepth(root *TreeNode) int { func maxDepth(root *TreeNode) int {
ans:=0 ans := 0
if root==nil{ if root == nil {
return 0 return 0
} }
queue:=list.New() queue := list.New()
queue.PushBack(root) queue.PushBack(root)
for queue.Len()>0{ for queue.Len() > 0 {
length:=queue.Len() length := queue.Len()
for i:=0;i<length;i++{ for i := 0; i < length; i++ {
node:=queue.Remove(queue.Front()).(*TreeNode) node := queue.Remove(queue.Front()).(*TreeNode)
if node.Left!=nil{ if node.Left != nil {
queue.PushBack(node.Left) queue.PushBack(node.Left)
} }
if node.Right!=nil{ if node.Right != nil {
queue.PushBack(node.Right) queue.PushBack(node.Right)
} }
} }
@ -2521,8 +2538,6 @@ func maxDepth(root *TreeNode) int {
} }
``` ```
JavaScript JavaScript
```javascript ```javascript
/** /**
@ -2763,30 +2778,29 @@ Go
* } * }
*/ */
func minDepth(root *TreeNode) int { func minDepth(root *TreeNode) int {
ans:=0 ans := 0
if root==nil{ if root == nil {
return 0 return 0
} }
queue:=list.New() queue := list.New()
queue.PushBack(root) queue.PushBack(root)
for queue.Len()>0{ for queue.Len() > 0 {
length:=queue.Len() length := queue.Len()
for i:=0;i<length;i++{ for i := 0; i < length; i++ {
node:=queue.Remove(queue.Front()).(*TreeNode) node := queue.Remove(queue.Front()).(*TreeNode)
if node.Left==nil&&node.Right==nil{//当前节点没有左右节点,则代表此层是最小层 if node.Left == nil && node.Right == nil { //当前节点没有左右节点,则代表此层是最小层
return ans+1//返回当前层 ans代表是上一层 return ans+1 //返回当前层 ans代表是上一层
} }
if node.Left!=nil{ if node.Left != nil {
queue.PushBack(node.Left) queue.PushBack(node.Left)
} }
if node.Right!=nil{ if node.Right != nil {
queue.PushBack(node.Right) queue.PushBack(node.Right)
} }
} }
ans++//记录层数 ans++//记录层数
} }
return ans+1 return ans+1
} }
``` ```

View File

@ -104,7 +104,7 @@ public:
### 深度优先遍历 ### 深度优先遍历
[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)中给出了前中后序迭代方式的写法,所以本可以很轻松的出如下迭代法的代码: [二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)中给出了前中后序迭代方式的写法,所以本可以很轻松的出如下迭代法的代码:
C++代码迭代法(前序遍历) C++代码迭代法(前序遍历)
@ -126,7 +126,7 @@ public:
} }
}; };
``` ```
如果这个代码看不懂的话可以回顾一下[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)。 如果这个代码看不懂的话可以回顾一下[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)。
我们在[二叉树:前中后序迭代方式的统一写法](https://programmercarl.com/二叉树的统一迭代法.html)中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。 我们在[二叉树:前中后序迭代方式的统一写法](https://programmercarl.com/二叉树的统一迭代法.html)中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。
@ -258,7 +258,6 @@ public:
### Java ### Java
```Java ```Java
//DFS递归 //DFS递归
class Solution { class Solution {
@ -294,8 +293,8 @@ class Solution {
while (size-- > 0) { while (size-- > 0) {
TreeNode node = deque.poll(); TreeNode node = deque.poll();
swap(node); swap(node);
if (node.left != null) {deque.offer(node.left);} if (node.left != null) deque.offer(node.left);
if (node.right != null) {deque.offer(node.right);} if (node.right != null) deque.offer(node.right);
} }
} }
return root; return root;
@ -364,13 +363,12 @@ class Solution:
### Go ### Go
递归版本的前序遍历 递归版本的前序遍历
```Go ```Go
func invertTree(root *TreeNode) *TreeNode { func invertTree(root *TreeNode) *TreeNode {
if root ==nil{ if root == nil {
return nil return nil
} }
root.Left,root.Right=root.Right,root.Left//交换 root.Left, root.Right = root.Right, root.Left //交换
invertTree(root.Left) invertTree(root.Left)
invertTree(root.Right) invertTree(root.Right)
@ -383,12 +381,14 @@ func invertTree(root *TreeNode) *TreeNode {
```go ```go
func invertTree(root *TreeNode) *TreeNode { func invertTree(root *TreeNode) *TreeNode {
if root==nil{ if root == nil {
return root return root
} }
invertTree(root.Left)//遍历左节点
invertTree(root.Right)//遍历节点 invertTree(root.Left) //遍历节点
root.Left,root.Right=root.Right,root.Left//交换 invertTree(root.Right) //遍历右节点
root.Left, root.Right = root.Right, root.Left //交换
return root return root
} }
``` ```
@ -397,18 +397,19 @@ func invertTree(root *TreeNode) *TreeNode {
```go ```go
func invertTree(root *TreeNode) *TreeNode { func invertTree(root *TreeNode) *TreeNode {
stack:=[]*TreeNode{} stack := []*TreeNode{}
node:=root node := root
for node!=nil||len(stack)>0{ for node != nil || len(stack) > 0 {
for node!=nil{ for node != nil {
node.Left,node.Right=node.Right,node.Left//交换 node.Left, node.Right = node.Right, node.Left //交换
stack=append(stack,node) stack = append(stack,node)
node=node.Left node = node.Left
} }
node=stack[len(stack)-1] node = stack[len(stack)-1]
stack=stack[:len(stack)-1] stack = stack[:len(stack)-1]
node=node.Right node = node.Right
} }
return root return root
} }
``` ```
@ -417,25 +418,26 @@ func invertTree(root *TreeNode) *TreeNode {
```go ```go
func invertTree(root *TreeNode) *TreeNode { func invertTree(root *TreeNode) *TreeNode {
stack:=[]*TreeNode{} stack := []*TreeNode{}
node:=root node := root
var prev *TreeNode var prev *TreeNode
for node!=nil||len(stack)>0{ for node != nil || len(stack) > 0 {
for node!=nil{ for node != nil {
stack=append(stack,node) stack = append(stack, node)
node=node.Left node = node.Left
} }
node=stack[len(stack)-1] node = stack[len(stack)-1]
stack=stack[:len(stack)-1] stack = stack[:len(stack)-1]
if node.Right==nil||node.Right==prev{ if node.Right == nil || node.Right == prev {
node.Left,node.Right=node.Right,node.Left//交换 node.Left, node.Right = node.Right, node.Left //交换
prev=node prev = node
node=nil node = nil
}else { } else {
stack=append(stack,node) stack = append(stack, node)
node=node.Right node = node.Right
} }
} }
return root return root
} }
``` ```
@ -444,21 +446,21 @@ func invertTree(root *TreeNode) *TreeNode {
```go ```go
func invertTree(root *TreeNode) *TreeNode { func invertTree(root *TreeNode) *TreeNode {
if root==nil{ if root == nil{
return root return root
} }
queue:=list.New() queue := list.New()
node:=root node := root
queue.PushBack(node) queue.PushBack(node)
for queue.Len()>0{ for queue.Len() > 0 {
length:=queue.Len() length := queue.Len()
for i:=0;i<length;i++{ for i := 0; i < length; i++ {
e:=queue.Remove(queue.Front()).(*TreeNode) e := queue.Remove(queue.Front()).(*TreeNode)
e.Left,e.Right=e.Right,e.Left//交换 e.Left, e.Right = e.Right, e.Left //交换
if e.Left!=nil{ if e.Left != nil {
queue.PushBack(e.Left) queue.PushBack(e.Left)
} }
if e.Right!=nil{ if e.Right != nil {
queue.PushBack(e.Right) queue.PushBack(e.Right)
} }
} }
@ -487,31 +489,31 @@ var invertTree = function(root) {
```javascript ```javascript
var invertTree = function(root) { var invertTree = function(root) {
//我们先定义节点交换函数 //我们先定义节点交换函数
const invertNode=function(root,left,right){ const invertNode = function(root, left, right) {
let temp=left; let temp = left;
left=right; left = right;
right=temp; right = temp;
root.left=left; root.left = left;
root.right=right; root.right = right;
} }
//使用迭代方法的前序遍历 //使用迭代方法的前序遍历
let stack=[]; let stack = [];
if(root===null){ if(root === null) {
return root; return root;
} }
stack.push(root); stack.push(root);
while(stack.length){ while(stack.length) {
let node=stack.pop(); let node = stack.pop();
if(node!==null){ if(node !== null) {
//前序遍历顺序中左右 入栈顺序是前序遍历的倒序右左中 //前序遍历顺序中左右 入栈顺序是前序遍历的倒序右左中
node.right&&stack.push(node.right); node.right && stack.push(node.right);
node.left&&stack.push(node.left); node.left && stack.push(node.left);
stack.push(node); stack.push(node);
stack.push(null); stack.push(null);
}else{ } else {
node=stack.pop(); node = stack.pop();
//节点处理逻辑 //节点处理逻辑
invertNode(node,node.left,node.right); invertNode(node, node.left, node.right);
} }
} }
return root; return root;
@ -521,27 +523,27 @@ var invertTree = function(root) {
```javascript ```javascript
var invertTree = function(root) { var invertTree = function(root) {
//我们先定义节点交换函数 //我们先定义节点交换函数
const invertNode=function(root,left,right){ const invertNode = function(root, left, right) {
let temp=left; let temp = left;
left=right; left = right;
right=temp; right = temp;
root.left=left; root.left = left;
root.right=right; root.right = right;
} }
//使用层序遍历 //使用层序遍历
let queue=[]; let queue = [];
if(root===null){ if(root === null) {
return root; return root;
} }
queue.push(root); queue.push(root);
while(queue.length){ while(queue.length) {
let length=queue.length; let length = queue.length;
while(length--){ while(length--) {
let node=queue.shift(); let node = queue.shift();
//节点处理逻辑 //节点处理逻辑
invertNode(node,node.left,node.right); invertNode(node, node.left, node.right);
node.left&&queue.push(node.left); node.left && queue.push(node.left);
node.right&&queue.push(node.right); node.right && queue.push(node.right);
} }
} }
return root; return root;
@ -760,7 +762,6 @@ func invertTree1(_ root: TreeNode?) -> TreeNode? {
} }
``` ```
### Swift
深度优先递归。 深度优先递归。
@ -808,9 +809,6 @@ func invertTree(_ root: TreeNode?) -> TreeNode? {
return root return root
} }
``` ```
### Scala
深度优先遍历(前序遍历): 深度优先遍历(前序遍历):
```scala ```scala
object Solution { object Solution {

View File

@ -14,7 +14,7 @@
<img src='https://img-blog.csdnimg.cn/20210219190809451.png' width=600 alt='二叉树大纲'> </img></div> <img src='https://img-blog.csdnimg.cn/20210219190809451.png' width=600 alt='二叉树大纲'> </img></div>
二叉树,大家对于二叉树其实都很熟悉了,本文呢我也不想教科书式的把二叉树的基础内容啰嗦一遍,所以下我讲的都是一些比较重点的内容。 二叉树,大家对于二叉树其实都很熟悉了,本文呢我也不想教科书式的把二叉树的基础内容啰嗦一遍,所以下我讲的都是一些比较重点的内容。
相信只要耐心看完,都会有所收获。 相信只要耐心看完,都会有所收获。
@ -83,7 +83,7 @@
那么链式存储方式就用指针, 顺序存储的方式就是用数组。 那么链式存储方式就用指针, 顺序存储的方式就是用数组。
顾名思义就是顺序存储的元素在内存是连续分布的,而链式存储则是通过指针把分布在散落在各个地址的节点串联一起。 顾名思义就是顺序存储的元素在内存是连续分布的,而链式存储则是通过指针把分布在各个地址的节点串联一起。
链式存储如图: 链式存储如图:
@ -143,7 +143,7 @@
最后再说一说二叉树中深度优先和广度优先遍历实现方式,我们做二叉树相关题目,经常会使用递归的方式来实现深度优先遍历,也就是实现前中后序遍历,使用递归是比较方便的。 最后再说一说二叉树中深度优先和广度优先遍历实现方式,我们做二叉树相关题目,经常会使用递归的方式来实现深度优先遍历,也就是实现前中后序遍历,使用递归是比较方便的。
**之前我们讲栈与队列的时候,就说过栈其实就是递归的一种实现结构**,也就说前中后序遍历的逻辑其实都是可以借助栈使用非递归的方式来实现的。 **之前我们讲栈与队列的时候,就说过栈其实就是递归的一种实现结构**,也就说前中后序遍历的逻辑其实都是可以借助栈使用非递归的方式来实现的。
而广度优先遍历的实现一般使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。 而广度优先遍历的实现一般使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。

View File

@ -36,13 +36,13 @@
**以下以前序遍历为例:** **以下以前序遍历为例:**
1. **确定递归函数的参数和返回值**因为要打印出前序遍历节点的数值所以参数里需要传入vector放节点的数值,除了这一点就不需要处理什么数据了也不需要有返回值所以递归函数返回类型就是void代码如下 1. **确定递归函数的参数和返回值**因为要打印出前序遍历节点的数值所以参数里需要传入vector放节点的数值,除了这一点就不需要处理什么数据了也不需要有返回值所以递归函数返回类型就是void代码如下
```cpp ```cpp
void traversal(TreeNode* cur, vector<int>& vec) void traversal(TreeNode* cur, vector<int>& vec)
``` ```
2. **确定终止条件**:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要结束了所以如果当前遍历的这个节点是空就直接return代码如下 2. **确定终止条件**在递归的过程中如何算是递归结束了呢当然是当前遍历的节点是空了那么本层递归就要结束了所以如果当前遍历的这个节点是空就直接return代码如下
```cpp ```cpp
if (cur == NULL) return; if (cur == NULL) return;