当前位置: 首页 > news >正文

代码随想录算法训练营第十一天--二叉树2 || 226.翻转二叉树 / 101.对称二叉树 / 104.二叉树的最大深度 / 111.二叉树的最小深度

代码随想录算法训练营第十一天--二叉树2 || 226.翻转二叉树 / 101.对称二叉树 / 104.二叉树的最大深度 / 111.二叉树的最小深度

  • 226.翻转二叉树(优先掌握递归)
    • 解题思路
      • 递归法
      • 迭代法 -- 深度优先遍历
      • 统一迭代法
      • 层序遍历 -- 广度优先搜索
  • 101.对称二叉树(优先掌握递归)
    • 解题思路
      • 递归法
    • 完整代码
      • 迭代法
    • 练习1
    • 练习2:
  • 104.二叉树的最大深度
    • 递归法
    • 层序遍历--迭代法
    • 练习:
      • 迭代法--层序遍历
      • 递归法
  • 111.二叉树的最小深度
    • 审题
    • 递归法
    • 迭代法--层序遍历

226.翻转二叉树(优先掌握递归)

解题思路

在这里插入图片描述
我们要翻转的不只是数字,而是指针。

递归法

/*** 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:TreeNode* invertTree(TreeNode* root) {if(root == NULL) return root;swap(root -> left, root -> right); // 中invertTree(root -> left); // 左invertTree(root -> right); // 右return root;}
};

上述代码使用的前序遍历法,当然也可以使用后序遍历法,但是**不能使用中序遍历法。
因为我们先翻转左子树,然后翻转中间节点,原来翻转过来的左子树翻转到右侧,我们又一次翻转右子树,那么把原来翻转过来的左子树又翻转回去了。而原来右子树没有进行翻转。
中序遍历代码如下:

class Solution {
public:TreeNode* invertTree(TreeNode* root) {if(root == NULL) return root;invertTree(root -> left); // 左swap(root -> left, root -> right); // 中invertTree(root -> left); // 右return root;}
};

迭代法 – 深度优先遍历

我们采用前序遍历

class Solution {
public:TreeNode* invertTree(TreeNode* root) {if (root == NULL) return root;stack<TreeNode*> st;st.push(root);while (!st.empty()) {TreeNode* node = st.top(); // 中st.pop();swap(node -> left, node -> right);if (node -> right) st.push(node -> right); // 右if (node -> left) st.push(node -> left); // 左}return root;}
};

统一迭代法

/*** 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:TreeNode* invertTree(TreeNode* root) {stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop();if (node -> right) st.push(node -> right); // 右if (node -> left) st.push(node -> left); // 左st.push(node); // 中st.push(NULL);} else {st.pop();node = st.top();st.pop();swap(node -> left, node -> right);}}return root;}
};

层序遍历 – 广度优先搜索

class Solution {
public:TreeNode* invertTree(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);while (!que.empty()) {int size = que.size();while (size --) {TreeNode* node = que.front(); // 中que.pop();swap(node -> left, node -> right); // 节点处理if (node -> left) que.push(node -> left); // 左if (node -> right) que.push(node -> right); // 右}}return root;}
};

101.对称二叉树(优先掌握递归)

解题思路

对于要搜集左右孩子,返回到中间节点的情况,我们一般采取后序遍历,这个非常重要。
在这里插入图片描述
这道题的关键是要判断外侧相等,里侧相等,比较根节点的左右两棵子树能否互相翻转。

递归法

递归三部曲
1.先判断返回值和传入的参数:
返回bool类型,参数就是左右节点

2.确定终止条件:

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true
  • 左右都不为空,左右值不同,return false
  • 左右都不为空,左右值相同,进入单层递归

3.确定单层递归逻辑

  • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
  • 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
  • 如果左右都对称就返回true ,有一侧不对称就返回false 。

完整代码

/*** 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:bool compare(TreeNode* left, TreeNode* right) {// 分五种情况if (left == NULL && right != NULL) return false; // 1.左空,右非空else if (left != NULL && right == NULL) return false; // 2.左非空,右空else if (left == NULL && right == NULL) return true; // 3.左空,右空else if (left -> val != right -> val) return false; // 4.左值 不等于 右值// 5.左值 = 右值bool outside = compare(left -> left, right -> right); // 左子树:左  右子树:右bool inside = compare(left -> right, right -> left); // 右    左bool issame = outside && inside; // 中    中return issame;}bool isSymmetric(TreeNode* root) {if (root == NULL) return true;return compare(root -> left, root -> right);}
};

迭代法

使用队列

class Solution {
public:bool isSymmetric(TreeNode* root) {if (root == NULL) return true;queue<TreeNode*> que;que.push(root -> left); // 将左子树头节点入队que.push(root -> right); // 将右子树头节点入队while (!que.empty()) { // 判断两个树是否相互翻转TreeNode* l = que.front(); que.pop();TreeNode* r = que.front(); que.pop();// 左右皆空,对称if (l == NULL && r == NULL) continue;// 左右一个为空 or 都不空但值不相等,不对称if (l == NULL || r == NULL || l -> val != r -> val)return false;que.push(l -> left); // 左节点左孩子que.push(r -> right); // 右节点右孩子que.push(l -> right); // 左节点右孩子que.push(r -> left); // 右节点左孩子}return true;}
};

练习1

100.相同的树

class Solution {
public:bool cmp(TreeNode* p, TreeNode* q) {if (p == NULL && q == NULL) return true;else if (p == NULL || q == NULL || p -> val != q -> val) return false;bool isl = cmp(p -> left, q -> left);bool isr = cmp(p -> right, q -> right);return isl && isr;}bool isSameTree(TreeNode* p, TreeNode* q) {return cmp(p, q);}
};

练习2:

572.另一棵树的子树

class Solution {
public:bool cmp(TreeNode* root, TreeNode* subRoot) {if (root == NULL && subRoot == NULL) return true;else if (root == NULL || subRoot == NULL || root -> val != subRoot -> val)return false;bool isl = cmp(root -> left, subRoot -> left);bool isr = cmp(root -> right, subRoot -> right);return isl && isr;}bool isSubtree(TreeNode* root, TreeNode* subRoot) {if (root == NULL) return false;return cmp(root, subRoot) ||isSubtree(root -> left, subRoot) ||isSubtree(root -> right, subRoot);}
};

这道题首先要判断根节点非空,防止对空节点进行操作。
然后我们就像100.相同的树一样去比较是否相等,不相等我们就递归isSubtree函数,直到找到相等的子树。

104.二叉树的最大深度

递归法

我们要分清高度深度的概念,对于一个二叉树,最上面的根节点的深度为1,高度就是深度的最大值,也就是说高度和深度是反转关系的。
一般使用后序遍历来求二叉树的最大高度,也就是二叉树的最大深度

public:int getDepth(TreeNode* node) {if (node == NULL) return 0; // 终止条件,最底层的下一层高度为0int leftDepth = getDepth(node -> left); // 左int rightDepth = getDepth(node -> right); // 右int depth = 1 + max(leftDepth, rightDepth); // 中return depth;}int maxDepth(TreeNode* root) {return getDepth(root);}
};

代码可以精简

class Solution {
public:int getDepth(TreeNode* node) {if (node == NULL) return 0; // 终止条件,最底层的下一层高度为0return 1 + max(getDepth(node -> left), getDepth(node -> right));}int maxDepth(TreeNode* root) {return getDepth(root);}
};

层序遍历–迭代法

class Solution {
public:int maxDepth(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);int depth = 0;while (!que.empty()) {int size = que.size();depth ++; // 记录深度while (size --) {TreeNode* node = que.front();que.pop();if (node -> left) que.push(node -> left);if (node -> right) que.push(node -> right);}}return ans;}
};

练习:

559.N叉树的最大深度

迭代法–层序遍历

class Solution {
public:int maxDepth(Node* root) {queue<Node*> que;if (root != NULL) que.push(root);int depth = 0;while (!que.empty()) {int size = que.size();depth ++;while (size --) {Node* node = que.front();que.pop();for (int i = 0; i < node -> children.size(); i++) {if (node -> children[i]) que.push(node -> children[i]);}}}return depth;}
};

递归法

class Solution {
public:int getDepth(Node* node) {if (node == NULL) return 0;int depth = 0;for (int i = 0; i < node -> children.size(); i++) {depth = max(depth, getDepth(node -> children[i]));}return depth + 1;}int maxDepth(Node* root) {return getDepth(root);}
};

最后为什么要加1呢,想想之前的二叉树,是左右,然后中,中是1 + max(左,右)。这里for循环就先当于左右,最后到中需要加1。

111.二叉树的最小深度

审题

这道题的最小深度,指的是叶子节点是指没有子节点的节点,有一个节点的,不叫最小深度,必须左右两个节点都无才算。
在这里插入图片描述

递归法

class Solution {
public:int getDepth(TreeNode* node) {int res = 0;if (node == NULL) return 0;int left = getDepth(node -> left);      // 左int right = getDepth(node -> right);    // 右// 中// 当一个左子树为空,右不为空,这时并不是最低点// 当一个右子树为空,左不为空,这时并不是最低点if (node -> left == NULL && node -> right != NULL) {res = 1 + right;} else if (node -> left != NULL && node -> right == NULL) {res = 1 + left;} else {res = 1 + min(left, right);}return res;}int minDepth(TreeNode* root) {return getDepth(root);}
};

迭代法–层序遍历

class Solution {
public:int minDepth(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);int depth = 0;while (!que.empty()) {int size = que.size();depth ++;while (size --) {TreeNode* node = que.front();que.pop();if (node -> left) que.push(node -> left);if (node -> right) que.push(node -> right);if (!node -> left && !node -> right) return depth;}}return depth;}
};

注意一下depth的位置,层序遍历是从上到下遍历,当左右无节点,那就直接返回。


文章转载自:

http://TahqbRFw.cjnfb.cn
http://EqsRJcuj.cjnfb.cn
http://A6WKQZpA.cjnfb.cn
http://CHId9NN1.cjnfb.cn
http://V8vSgC7p.cjnfb.cn
http://CnHrMaex.cjnfb.cn
http://aAT82nf9.cjnfb.cn
http://Uka8xP14.cjnfb.cn
http://T1UXwo0Z.cjnfb.cn
http://C58fwZ7K.cjnfb.cn
http://4n7tHFwq.cjnfb.cn
http://vR8mqDC3.cjnfb.cn
http://rDyVPdJ6.cjnfb.cn
http://dPJwfyy1.cjnfb.cn
http://oN7oUkAR.cjnfb.cn
http://qO33wiH2.cjnfb.cn
http://t6GUUzq3.cjnfb.cn
http://tLSmfoCG.cjnfb.cn
http://7spVJ9S0.cjnfb.cn
http://Ybbd2cPE.cjnfb.cn
http://PrfmuMJt.cjnfb.cn
http://ik8YXIEf.cjnfb.cn
http://5OoMJ3EL.cjnfb.cn
http://yxpzVqDH.cjnfb.cn
http://B0jve9Sp.cjnfb.cn
http://frU7Yk3P.cjnfb.cn
http://tvZhLSRz.cjnfb.cn
http://1ZoDqAaa.cjnfb.cn
http://W06vNliM.cjnfb.cn
http://6lRUPXks.cjnfb.cn
http://www.dtcms.com/a/383421.html

相关文章:

  • IDEA编译器设置代码注释模板
  • 10-鼠标操作的处理
  • efcore 对象内容相同 提交MSSQL后数据库没有更新
  • Docker 容器化
  • 玩转Docker | 使用Docker部署OmniTools自托管IT工具箱
  • 类的组合(对比继承)
  • python爬虫的逆向技术讲解
  • Cookie 和 Session
  • 【WebSocket✨】入门之旅(四):WebSocket 的性能优化
  • 40分钟的Docker实战攻略
  • JavaScript 运算符完全指南:从基础到位运算
  • visual studio快捷键
  • 第21课:成本优化与资源管理
  • 5【鸿蒙/OpenHarmony/NDK】应用太卡?用 Node-API 异步任务解决:从卡顿根源到流畅方案
  • 利用OpenCV进行对答题卡上的答案进行识别的案例
  • 如何用 Rust 实现的基础屏幕录制程序?
  • 认知语义学隐喻理论对人工智能自然语言处理中深层语义分析的赋能与挑战
  • 常见索引失效场景及原因分析(含示例)
  • 嵌入式Linux常用命令
  • xtuoj Rectangle
  • C++内存管理:new与delete的深层解析
  • Nginx 实战系列(十)—— 搭建LNMP环境与部署Discuz!社区论坛指南
  • 计算机视觉案例分享之答题卡识别
  • 端口打开与服务可用
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘requests’ 问题
  • 使用Docker和虚拟IP在一台服务器上灵活部署多个Neo4j实例
  • Web前端面试题(2)
  • 硬件开发_基于物联网的仓鼠饲养监测系统
  • 资产负债表、利润表、经营现金流、统计指标计算程序
  • JWT简介