《录鼎记》第十三章——有史最长篇
今日内容:
- 层序遍历 10
- 226.翻转二叉树
- 101.对称二叉树 2
一、二叉树的层序遍历
力扣题目链接 (opens new window)
思路一:队列实现,将根节点推入,之后在队列非空时,记录一层中的元素数量,然后遍历将该节点的值记录在vec中,左右子节点送入队列,等待下一次循环,直到队列为空——即层序遍历完毕。
/*** 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;if(root!=NULL) que.push(root);vector<vector<int>> result;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);} result.push_back(vec);}return result;}
};
思路二:递归法,主要还是按之前讲的三步走,确定参数:层级遍历,要有节点,要有存节点的容器,要有层数(用于记录存放在容器的哪一层)
终止条件即为节点为空
中间则为先是在容器大小等于深度时,创建新的一层,然后是将该节点存入对应层,将左右子节点放入函数中。
主函数则是递归函数的入口,最后返回容器result。
class Solution {
public:void di(TreeNode* cur,vector<vector<int>>& vec,int depth){if(cur==NULL) return;if(vec.size()==depth) vec.push_back(vector<int>());vec[depth].push_back(cur->val);di(cur->left,vec,depth+1);di(cur->right,vec,depth+1);}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;int depth =0;di(root,result,depth);return result;}
};
控制台
二、层次遍历II
力扣题目链接 (opens new window)
此题仅为将结果用reverse反转
reverse(result.begin(), result.end());
三、二叉树的右视图
力扣题目链接 (opens new window)
力扣题目链接 (opens new window)
思路:本体就是一个变形,指在遍历到该层最后一个节点的时候返回到结果中。
/*** 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<int> rightSideView(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);vector<int> result;while(!que.empty()){int size =que.size();for(int i =0;i<size;i++){TreeNode* node =que.front();que.pop(); if(i==size-1) result.push_back(node->val);if(node->left) que.push(node->left);if(node->right) que.push(node->right);}}return result;}
};
四、二叉树的层平均值
力扣题目链接 (opens new window)
思路:此题也是一个变型,就是将一层所有元素相加后除元素数量就可以,但要注意变量类型
/*** 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<double> averageOfLevels(TreeNode* root) {queue<TreeNode*> que;vector<double> result;if(root!=NULL) que.push(root);while(!que.empty()){int size =que.size();double sum =0;for(int i=0;i<size;i++){TreeNode* cur =que.front();que.pop();sum+=cur->val;if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}result.push_back(sum/size);}return result;}
};
五、n叉树层序遍历
力扣题目链接 (opens new window)
本题和首题是差不多的,就是需要遍历多个孩子节点
class Solution {
public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> que;if(root!=NULL) que.push(root);vector<vector<int>> result;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 j=0;j<node->children.size();j++){if(node->children[j]) que.push(node->children[j]);}}result.push_back(vec);}return result;}
};
六、在每个树行找最大值
力扣题目链接 (opens new window)
思路:这题也是变形,只需要逐个比较,将最后的值插入。
class Solution {
public:vector<int> largestValues(TreeNode* root) {queue<TreeNode*> que;vector<int> result;if(root!=NULL) que.push(root);while(!que.empty()){int size =que.size();int max1 =INT_MIN;for(int i=0;i<size;i++){TreeNode* cur =que.front();que.pop();max1 = max(max1,cur->val);if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}result.push_back(max1);}return result;}
};
需要注意max初始值不能取0。
七、填充每个节点的下一个右侧节点指针
力扣题目链接 (opens new window)
思路:需要把每一层的第一个节点拿出做头节点,最后将最后一个节点指向空,中间为前节点的指针指向现节点,现节点变为了前节点。
/*
// Definition for a Node.
class Node {
public:int val;Node* left;Node* right;Node* next;Node() : val(0), left(NULL), right(NULL), next(NULL) {}Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}Node(int _val, Node* _left, Node* _right, Node* _next): val(_val), left(_left), right(_right), next(_next) {}
};
*/class Solution {
public:Node* connect(Node* root) {queue<Node*> que;if(root!=NULL) que.push(root);while(!que.empty()){int size =que.size();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;Nodepre=Nodepre->next;}if(node->left) que.push(node->left);if(node->right) que.push(node->right);}Nodepre->next=NULL;}return root;}
};
八、填充每个节点的下一个右侧节点指针||
力扣题目链接 (opens new window)
虽然由完美二叉树变味了二叉树,但代码和逻辑没有区别
九、二叉树的最大深度
力扣题目链接 (opens new window)
思路:也为变形,每次从队列中取一列的时候深度加一
/*** 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:int maxDepth(TreeNode* root) {queue<TreeNode*> que;int result=0;if(root!=NULL){que.push(root);}while(!que.empty()){int size = que.size();result++;for(int i=0;i<size;i++){TreeNode* cur =que.front();que.pop();if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}}return result;}
};
十、二叉树的最小深度
力扣题目链接 (opens new window)
需要注意的是只有左右孩子均为空才为最小
/*** 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:int maxDepth(TreeNode* root) {queue<TreeNode*> que;int result=0;if(root!=NULL){que.push(root);}while(!que.empty()){int size = que.size();result++;for(int i=0;i<size;i++){TreeNode* cur =que.front();que.pop();if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}}return result;}
};
十一、翻转二叉树
力扣题目链接 (opens new window)
题目虽然简单但也考基础
递归三部曲:
- 确定递归函数的参数和返回值
参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。
返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode*
。
TreeNode* invertTree(TreeNode* root)
1
- 确定终止条件
当前节点为空的时候,就返回
if (root == NULL) return root;
1
- 确定单层递归的逻辑
因为是先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
class Solution {
public:void fanzhuan(TreeNode* node){if(node==NULL) return;swap(node->left,node->right);fanzhuan(node->left);fanzhuan(node->right);}TreeNode* invertTree(TreeNode* root) {fanzhuan(root);return root;}
有1说1,我写的比题解复杂多了。其实这道题也可以用深度和广度优先算法做
深度前序(非统一):
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->left) st.push(node->left);if(node->right) st.push(node->right);}return root;}
};
统一写法前序深度:
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->left) st.push(node->left);if(node->right) st.push(node->right);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();for(int i = 0;i<size;i++){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;}
};
由于迭代中序使用栈处理,左右节点在翻转前压入了栈,所以避免了翻转两次的情况。
而递归需要两次遍历左孩子,为避免翻转两次、
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;}
};
十二、对称二叉树
力扣题目链接 (opens new window)
递归三部曲:
- 确定递归函数的参数和返回值
因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。
返回值自然是bool类型。
代码如下:
bool compare(TreeNode* left, TreeNode* right)
2、确定终止条件
要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。
节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下我称之为左节点右节点)
- 左节点为空,右节点不为空,不对称,return false
- 左不为空,右为空,不对称 return false
- 左右都为空,对称,返回true
此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:
- 左右都不为空,比较节点数值,不相同就return false
此时左右节点不为空,且数值也不相同的情况我们也处理了。
代码如下:
if (left == NULL && right != NULL) return false;
else if (left != NULL && right == NULL) return false;
else if (left == NULL && right == NULL) return true;
else if (left->val != right->val) return false; // 注意这里我没有使用else
注意上面最后一种情况,我没有使用else,而是else if, 因为我们把以上情况都排除之后,剩下的就是 左右节点都不为空,且数值相同的情况
3、确定单层递归的逻辑
此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
- 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
- 比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
- 如果左右都对称就返回true ,有一侧不对称就返回false 。
代码如下:
bool outside = compare(left->left, right->right); // 左子树:左、 右子树:右
bool inside = compare(left->right, right->left); // 左子树:右、 右子树:左
bool isSame = outside && inside; // 左子树:中、 右子树:中(逻辑处理)
return isSame;
整体代码
/*** 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 issame(TreeNode* left,TreeNode*right){if(left==NULL&&right!=NULL) return false;else if(left!=NULL&&right==NULL) return false;else if(left==NULL&&right==NULL) return true;else if(left->val!=right->val) return false;bool outside =issame(left->left,right->right);bool inside =issame(left->right,right->left);bool isss =outside&&inside;return isss;}bool isSymmetric(TreeNode* root) {if(root==NULL) return true;return issame(root->left,root->right);}
};
使用队列:是将两侧对称放入队列再取出进行比较,有不一样返回false,到最后都相同返回true
使用栈:和队列相同
东西很多,花了两小时。还是要重视基础啊
题解:代码随想录代码随想录
代码随想录
《录鼎记》第十三章——有史最长篇相关推荐
- 刷题体验第一天——《录鼎记》第一章
先来解释为啥用这个标题(除了蹭一点之外呢),第一个字,代表刷题的题目来源是<代码随想录>,而鼎有两种解释,一种是谐音顶(原谅作者现在还是个菜鸟),另一个也是时刻提醒自己,不能眼高手低,要切 ...
- 《录鼎记》——重启之回溯part03
第七章 回溯算法part03 39. 组合总和 40.组合总和II 131.分割回文串 一.组合总和 力扣题目链接 (opens new window) 回溯三部曲 1.回溯函数参数及返回值,用par ...
- 《录鼎记》——重启之回溯part04
今日任务: 93.复原IP地址 78.子集 90.子集II 一.复原IP地址 力扣题目链接 (opens new window) 如果说能想到和上到题一样是切割,就有基本的思路了. 回溯三部曲:1.递 ...
- 《录鼎记》——重启之回溯part05
今日任务 * 491.递增子序列 * 46.全排列 * 47.全排列 II 一.递增子序列 力扣题目链接 (opens new window) class Solution { public:vect ...
- 价格奥秘-在超市遇见亚当斯密--第十三章 把未来留给未知的一切
第十三章把未来留给未知的一切 拉蒙在20年前的那个春天(他当时即将毕业,并在为参加温布尔登网球赛做准备),曾和鲁思多次讨论经济学,但鲁思那时的真实想法,拉蒙在20年之后才发现.在20年之后8月一个晴朗 ...
- 【Java数据结构与算法】第十三章 二叉排序树和平衡二叉树
第十三章 二叉排序树和平衡二叉树 文章目录 第十三章 二叉排序树和平衡二叉树 一.二叉排序树 1.介绍 2.创建 3.删除结点 4.代码实现 二.平衡二叉树 1.引入 2.介绍 3.插入结点 4.删除 ...
- 《操作系统真象还原》第十三章 ---- 编写硬盘驱动软件 行百里者半九十终成时喜悦溢于言表
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 提前需要准备编写的函数 实现printk 实现sprintf函数 创建从盘 创建从盘的步骤 修改后的bochsrc.d ...
- 《Dreamweaver CS6 完全自学教程》笔记 第十三章:Dreamweaver 中的 HTML 代码
文章目录 第十三章:Dreamweaver 中的 HTML 代码 13.1 HTML 介绍 13.2 HTML 的基本结构 13.2.1 单标签 13.2.2 双标签 13.2.3 标签属性 13.3 ...
- 【正点原子Linux连载】第二十三章 音频应用编程-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1
第二十三章 音频应用编程 ALPHA I.MX6U开发板支持音频,板上搭载了音频编解码芯片WM8960,支持播放以及录音功能! 本章我们来学习Linux下的音频应用编程,音频应用编程相比于前面几个章节 ...
最新文章
- 小武机器人怎么连不上网_电脑连不上网?原因在这里
- python将数字转变为中文读法-Python转换数字到中文大写格式
- com+ 三层布署[未成功验证]
- 孔雀东南飞用mysql存储_PowerDesigner使用建议(完整版) 用实体关系图进行数据库建模...
- cocosStudio制作ScrollView并在cocos2dx 3.0中使用。
- java 3des加密_Java使用3DES加密解密的流程 - 3des加密解密详细解释
- PageHelper分页插件使用
- 【VS开发】VS2010中导入ActiveX控件
- Hibernate ,Mybatis 区别,以及各自的一级,二级缓存理解
- Linux 误删除 /boot分区 的解救办法
- mod_signalwire.c:1009 Next SignalWire adoption
- 《区块链技术指南》笔记
- linux下编译libyuv,Android ndk cmake编译libyuv
- Cisco防火墙概述和产品线
- 图片验证码的逻辑实现
- 百度网盘 api抓包
- 小企业怎样选择服务器和操作系统
- ERROR 1366 (HY000): Incorrect string value: ‘\xE8\xB5\xB5 \xE9\x9B...‘ for column ‘s_name‘ at row 1
- jquery入门介绍
- 开源AI项目-老照片修复之 Bringing Old Photos Back to Life
热门文章
- 网页自动识别跳转手机或pc
- android cmd命令行删除文件夹,文件
- 对未来计算机畅想英语作文80词,关于我的未来英语作文80词
- 简单理解call_user_func和call_user_func_array两个函数
- 财务分析报表分享|现金流量表可视化
- 数据分析:Numpy模块(一)
- 2019,我是如何转向战略成功,并成功跑通一个现金流项目的
- strftime函数python_PyThon中time strftime()函数用法
- 基础知识 -- 问答
- 链式法则求导的原则和梯度回传