我在代码随想录|写代码Day16之二叉树-二叉树的层序遍历, 二叉树的层次遍历 II, 二叉树的右视图,N叉树的层序遍历,在每个树行中找最大值,填充每个节点的下一个右侧节点指针,二叉树的最大/小深度
学习目标:
博主介绍: 27dCnc
专题 : 数据结构帮助小白快速入门
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆
主题: 二叉树
今日份打卡
- 代码随想录-二叉树
文章目录
- 学习目标:
- 主题: 二叉树
- 学习内容:
- 内容讲解:
- [ 二叉树的层序遍历模版题](https://leetcode.cn/problems/binary-tree-level-order-traversal/description/)
- [二叉树的层序遍历 II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/)
- 199.二叉树的右视图
- [637. 二叉树的层平均值](https://leetcode.cn/problems/average-of-levels-in-binary-tree/description/)
- [429. N 叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/)
- 515.在每个树行中找最大值
- 116.填充每个节点的下一个右侧节点指针
- [117. 填充每个节点的下一个右侧节点指针 II](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/description/)
- [104. 二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/description/)
- 111.二叉树的最小深度
- 学习时间:
- 学习产出:
学习内容:
- 二叉树的层序遍历
- 二叉树的层次遍历 II
- 二叉树的右视图
- 二叉树的层平均值
- N叉树的层序遍历
- 在每个树行中找最大值
- 填充每个节点的下一个右侧节点指针
- 填充每个节点的下一个右侧节点指针II
- 二叉树的最大深度
- 二叉树的最小深度
内容讲解:
二叉树的层序遍历模版题
题目
图解
思路解析:
俩个重要容器
queue<TreeNode*>que;
队列- `vector<vector> 二维数组
队列用于储存每一层的结点
二维数组用于储存每已成都结果
终止条件是队列为空,只要根结点不为空,就将根结点放入队列,进入循环后,队列的长度为每一层遍历的大小,然后将父节点的孩子结点放入队列,然后将父节点出队列,将父节点的值储存在新建立的
vector<int>
中然后不断循环每一层循环后将vwctor<int>
放入vector<vector<int>>
中
层序遍历顺序
- 创建队列储存每一层结果
- 创建二维数组用于储存每一层的结果
- 进入循环去遍历每一层结果,终止条件是队列为空
- 用 size 储存二叉树中每一层的数组
- 应
vector<int>
储存每一层数组的值- 将根结点的左右孩子放入队列中
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> ans;
if(root != nullptr) que.push(root);
while(!que.empty()) {
int size = que.size();
vector<int>vec;
for(int i = 0;i < size;i++) {
TreeNode*node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(vec);
}
return ans;
}
};
二叉树的层序遍历 II
题目
代码
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> que;
if(root != nullptr) que.push(root);
vector<vector<int>> ans;
while(!que.empty()){
int size = que.size();
vector<int> vec;
for(int i=0;i<size;i++){
TreeNode*node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
ans.push_back(vec);//记录每一层
}
reverse(ans.begin(),ans.end());
return ans;
}
};
reverse()
用于反转层序遍历结果可以达到从下到上的遍历效果
199.二叉树的右视图
题目
思路
可以层序遍历然后取层序遍历的最右边的数据,然后将数据存储到vector数组中返回
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了,其中result数组即vector数组。
代码
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int>ans;
queue<TreeNode*>que;
if(root != nullptr) que.push(root);
while(!que.empty()) {
int size = que.size();
for(int i=0;i<size;i++){
TreeNode*node = que.front();//取栈顶元素即上一层元素
que.pop();//弹出元素准备放入该弹出元素的孩子结点
if(i==size-1) ans.push_back(node->val);//没一层的最右的结点
if(node->left) que.push(node->left);遍历树
if(node->right) que.push(node->right);
}
}
return ans;
}
};
637. 二叉树的层平均值
题目
思路: 本题就是层序遍历的时候把一层求个总和在取一个均值。
代码
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double>ans;
queue<TreeNode*>que;
if(root != nullptr) que.push(root);
while(!que.empty()) {
long long sum = 0;
int size = que.size();
vector<int>vec;
for(int i=0;i<size;i++) {
TreeNode*node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
for(int i=0;i<size;i++) {
sum+=vec[i];
}
ans.push_back(1.0*sum/size);
}
return ans;
}
};
层序遍历模版 + 求数组平均值 + 将数组传入改为将平均值传入
429. N 叉树的层序遍历
题目
层序遍历进阶
N叉树与二叉树的不同
- N叉树相较于二叉树孩子数量不同而且不国定
- 结构并不平衡孩子结点的定义规则不同
N叉树定义
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
二叉树定义
Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
解决多孩子问题可以用遍历数组的方式
因为孩子是通过vector<Node*> children;
储存的所以可以使用 node->children.size()
统计数组长度,通过 if(node -> children[i]) que.push(node->children[i]);
去遍历树的孩子。
代码
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
queue<Node*>que;
if(root != nullptr) que.push(root);
vector<vector<int>> ans;
while(!que.empty()) {
int size = que.size();
vector<int>vec;
for(int i=0;i < size;i++) {
Node*node = que.front();
que.pop();
vec.push_back(node->val);
for(int i =0;i< node->children.size() ; i++) {
if(node -> children[i]) que.push(node->children[i]);
}
}
ans.push_back(vec);
}
return ans;
}
};
515.在每个树行中找最大值
题目
思路 : 层序遍历,取每一层的最大值
代码
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
queue<TreeNode*> que;
if(root != nullptr) que.push(root);
vector<int> ans;
while(!que.empty()){
int size = que.size();
vector<int> vec;
for(int i=0;i<size;i++){
TreeNode*node = que.front();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
sort(vec.begin(),vec.end());
ans.push_back(vec[size-1]);//记录每一层最大值
}
return ans;
}
};
其他版本
Python
class Solution:
def largestValues(self, root: TreeNode) -> List[int]:
if not root:
return []
result = []
queue = collections.deque([root])
while queue:
level_size = len(queue)
max_val = float('-inf')
for _ in range(level_size):
node = queue.popleft()
max_val = max(max_val, node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(max_val)
return result
Java
class Solution {
public List<Integer> largestValues(TreeNode root) {
if(root == null){
return Collections.emptyList();
}
List<Integer> result = new ArrayList();
Queue<TreeNode> queue = new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
int max = Integer.MIN_VALUE;
for(int i = queue.size(); i > 0; i--){
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
result.add(max);
}
return result;
}
}
Go
/**
515. 在每个树行中找最大值
*/
func largestValues(root *TreeNode) []int {
if root == nil {
//防止为空
return nil
}
queue := list.New()
queue.PushBack(root)
ans := make([]int, 0)
temp := math.MinInt64
// 层序遍历
for queue.Len() > 0 {
//保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
length := queue.Len()
for i := 0; i < length; i++ {
node := queue.Remove(queue.Front()).(*TreeNode)//出队列
// 比较当前层中的最大值和新遍历的元素大小,取两者中大值
temp = max(temp, node.Val)
if node.Left != nil {
queue.PushBack(node.Left)
}
if node.Right != nil {
queue.PushBack(node.Right)
}
}
ans = append(ans, temp)
temp = math.MinInt64
}
return ans
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
116.填充每个节点的下一个右侧节点指针
题目
样例图解
思路
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了
class Solution {
public:
Node* connect(Node* root) {
queue<Node*> que;
if (root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
// vector<int> vec;
Node* nodePre;
Node* node;
for (int i = 0; i < size; i++) {
if (i == 0) {
nodePre = que.front(); // 取出一层的头结点
que.pop();
node = nodePre;
} else {
node = que.front();
que.pop();
nodePre->next = node; // 本层前一个节点next指向本节点
nodePre = nodePre->next;
}
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
nodePre->next = NULL; // 本层最后一个节点指向NULL
}
return root;
}
};
117. 填充每个节点的下一个右侧节点指针 II
题目
思路
这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道
class Solution {
public:
Node* connect(Node* root) {
queue<Node*> que;
if (root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
vector<int> vec;
Node* nodePre;
Node* node;
for (int i = 0; i < size; i++) {
if (i == 0) {
nodePre = que.front(); // 取出一层的头结点
que.pop();
node = nodePre;
} else {
node = que.front();
que.pop();
nodePre->next = node; // 本层前一个节点next指向本节点
nodePre = nodePre->next;
}
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
nodePre->next = NULL; // 本层最后一个节点指向NULL
}
return root;
}
};
104. 二叉树的最大深度
题目
思路
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度
递归法
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int depth_left = maxDepth(root->left);
int depth_right = maxDepth(root->right);
return 1 + max(depth_left, depth_right);
}
};
迭代法
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) return 0;
int depth = 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return depth;
}
};
回溯法
class Solution {
public:
int result;
void getDepth(TreeNode* node,int depth) {
result = depth > result ? depth : result;//中
if (node->left == nullptr && node->right == nullptr) return ;
if(node->left) { //左
depth++;//深度+1
getDepth(node->left,depth);
depth--;//回溯深度-1 ,变向状态转换
}
if (node->right) {
depth++;//深度+1
getDepth(node->right,depth);
depth--;//回溯深度-1 ,变向状态转换
}
return ;
}
int maxDepth(TreeNode* root) {
result=0;
if (root == nullptr) return result;
getDepth(root,1);
return result;
}
};
111.二叉树的最小深度
题目
思路
相对于 104.二叉树的最大深度
,本题还也可以使用层序遍历的方式来解决,思路是一样的。
需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点
递归法
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int depth_left = minDepth(root->left);
int depth_right = minDepth(root->right);
if(root->left == nullptr || root->right == nullptr){
return 1 + max(depth_left, depth_right);
}else{
return 1 + min(depth_left, depth_right);
}
}
};
学习时间:
- 周一至周五晚上 7 点—晚上9点
- 周六上午 9 点-上午 11 点
- 周日下午 3 点-下午 6 点
学习产出:
- 技术笔记 2 遍
- CSDN 技术博客 3 篇
- 习的 vlog 视频 1 个
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~
本文作者:2c237c6
本文链接:https://www.cnblogs.com/27dCnc/p/18568653
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步