今日内容:

  • 层序遍历 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)

题目虽然简单但也考基础

递归三部曲:

  1. 确定递归函数的参数和返回值

参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。

返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode*

TreeNode* invertTree(TreeNode* root)

1

  1. 确定终止条件

当前节点为空的时候,就返回

if (root == NULL) return root;

1

  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)

递归三部曲:

  1. 确定递归函数的参数和返回值

因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。

返回值自然是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

使用栈:和队列相同

东西很多,花了两小时。还是要重视基础啊

题解:代码随想录代码随想录

代码随想录

《录鼎记》第十三章——有史最长篇相关推荐

  1. 刷题体验第一天——《录鼎记》第一章

    先来解释为啥用这个标题(除了蹭一点之外呢),第一个字,代表刷题的题目来源是<代码随想录>,而鼎有两种解释,一种是谐音顶(原谅作者现在还是个菜鸟),另一个也是时刻提醒自己,不能眼高手低,要切 ...

  2. 《录鼎记》——重启之回溯part03

    第七章 回溯算法part03 39. 组合总和 40.组合总和II 131.分割回文串 一.组合总和 力扣题目链接 (opens new window) 回溯三部曲 1.回溯函数参数及返回值,用par ...

  3. 《录鼎记》——重启之回溯part04

    今日任务: 93.复原IP地址 78.子集 90.子集II 一.复原IP地址 力扣题目链接 (opens new window) 如果说能想到和上到题一样是切割,就有基本的思路了. 回溯三部曲:1.递 ...

  4. 《录鼎记》——重启之回溯part05

    今日任务 * 491.递增子序列 * 46.全排列 * 47.全排列 II 一.递增子序列 力扣题目链接 (opens new window) class Solution { public:vect ...

  5. 价格奥秘-在超市遇见亚当斯密--第十三章 把未来留给未知的一切

    第十三章把未来留给未知的一切 拉蒙在20年前的那个春天(他当时即将毕业,并在为参加温布尔登网球赛做准备),曾和鲁思多次讨论经济学,但鲁思那时的真实想法,拉蒙在20年之后才发现.在20年之后8月一个晴朗 ...

  6. 【Java数据结构与算法】第十三章 二叉排序树和平衡二叉树

    第十三章 二叉排序树和平衡二叉树 文章目录 第十三章 二叉排序树和平衡二叉树 一.二叉排序树 1.介绍 2.创建 3.删除结点 4.代码实现 二.平衡二叉树 1.引入 2.介绍 3.插入结点 4.删除 ...

  7. 《操作系统真象还原》第十三章 ---- 编写硬盘驱动软件 行百里者半九十终成时喜悦溢于言表

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 提前需要准备编写的函数 实现printk 实现sprintf函数 创建从盘 创建从盘的步骤 修改后的bochsrc.d ...

  8. 《Dreamweaver CS6 完全自学教程》笔记 第十三章:Dreamweaver 中的 HTML 代码

    文章目录 第十三章:Dreamweaver 中的 HTML 代码 13.1 HTML 介绍 13.2 HTML 的基本结构 13.2.1 单标签 13.2.2 双标签 13.2.3 标签属性 13.3 ...

  9. 【正点原子Linux连载】第二十三章 音频应用编程-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1

    第二十三章 音频应用编程 ALPHA I.MX6U开发板支持音频,板上搭载了音频编解码芯片WM8960,支持播放以及录音功能! 本章我们来学习Linux下的音频应用编程,音频应用编程相比于前面几个章节 ...

最新文章

  1. 小武机器人怎么连不上网_电脑连不上网?原因在这里
  2. python将数字转变为中文读法-Python转换数字到中文大写格式
  3. com+ 三层布署[未成功验证]
  4. 孔雀东南飞用mysql存储_PowerDesigner使用建议(完整版) 用实体关系图进行数据库建模...
  5. cocosStudio制作ScrollView并在cocos2dx 3.0中使用。
  6. java 3des加密_Java使用3DES加密解密的流程 - 3des加密解密详细解释
  7. PageHelper分页插件使用
  8. 【VS开发】VS2010中导入ActiveX控件
  9. Hibernate ,Mybatis 区别,以及各自的一级,二级缓存理解
  10. Linux 误删除 /boot分区 的解救办法
  11. mod_signalwire.c:1009 Next SignalWire adoption
  12. 《区块链技术指南》笔记
  13. linux下编译libyuv,Android ndk cmake编译libyuv
  14. Cisco防火墙概述和产品线
  15. 图片验证码的逻辑实现
  16. 百度网盘 api抓包
  17. 小企业怎样选择服务器和操作系统
  18. ERROR 1366 (HY000): Incorrect string value: ‘\xE8\xB5\xB5 \xE9\x9B...‘ for column ‘s_name‘ at row 1
  19. jquery入门介绍
  20. 开源AI项目-老照片修复之 Bringing Old Photos Back to Life

热门文章

  1. 网页自动识别跳转手机或pc
  2. android cmd命令行删除文件夹,文件
  3. 对未来计算机畅想英语作文80词,关于我的未来英语作文80词
  4. 简单理解call_user_func和call_user_func_array两个函数
  5. 财务分析报表分享|现金流量表可视化
  6. 数据分析:Numpy模块(一)
  7. 2019,我是如何转向战略成功,并成功跑通一个现金流项目的
  8. strftime函数python_PyThon中time strftime()函数用法
  9. 基础知识 -- 问答
  10. 链式法则求导的原则和梯度回传