代码随想录【day 14 二叉树】| 层序遍历 226.翻转二叉树 101.对称二叉树

  • 层序遍历
    • 卡哥文解
    • 视频讲解
    • 题目链接:102.二叉树的层序遍历
    • 解题思路
    • 代码实现
    • 题目链接:107.二叉树的层序遍历II
    • 解题思路
    • 代码实现
    • 题目链接:199.二叉树的右视图
    • 解题思路
    • 代码实现
    • 题目链接:637.二叉树的层平均值
    • 解题思路
    • 代码实现
    • 题目链接:429.N叉树的层序遍历
    • 解题思路
    • 代码实现
    • 题目链接:515.在每个树行中找最大值
    • 解题思路
    • 代码实现
    • 题目链接:116.填充每个节点的下一个右侧节点指针
    • 解题思路
    • 代码实现
    • 题目链接:117.填充每个节点的下一个右侧节点指针II
    • 解题思路
    • 代码实现
    • 题目链接:111.二叉树的最小深度
    • 解题思路
    • 代码实现
    • 题目链接:104.二叉树的最大深度
    • 解题思路
    • 代码实现
  • LeetCode 226.翻转二叉树 (优先掌握递归)
    • 题目链接:LeetCode226.翻转二叉树
    • 卡哥文解
    • 视频讲解
    • 解题思路
    • 代码实现
  • LeetCode 101. 对称二叉树
    • 题目链接:101.对称二叉树
    • 卡哥文解
    • 视频讲解
    • 解题思路
    • 实现难点
    • 代码实现
  • 补充
  • day14总结复盘

层序遍历

对应题目
102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度

二叉树的层序遍历 相当于图论里的广度优先搜索 (队列实现)
二叉树的递归遍历 相当于图论里的深度优先搜索

卡哥文解

视频讲解

题目链接:102.二叉树的层序遍历

  • 题目描述: 给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)。

解题思路

1、通过队列保存每一层里遍历过的元素
2、对队列里的每一层元素数量size进行记录,因为队列里存放的数可能有第二层的也有可能有第三层的
3、在第二层元素弹出的同时,将其左右孩子(第三层)也同时加入队列,遍历完第二层所有元素之后,其实第三层所有元素都已在队列里,记录第三层元素数量
4、终止条件:队列里没有元素->遍历完

代码实现

/*** 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>>result; //二维数组记录结果 层数以及if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();vector<int> vec; // 一维数组暂时记录该层结果while(size--){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;}
};

题目链接:107.二叉树的层序遍历II

  • 题目描述: 给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)。

解题思路

1、在102二叉树的层序遍历结果的基础上进行翻转

代码实现

/*** 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>> levelOrderBottom(TreeNode* root) {queue<TreeNode*>que;vector<vector<int>>result;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();vector<int>vec;while(size--){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);}reverse(result.begin(),result.end());return result;}
};

题目链接:199.二叉树的右视图

  • 题目描述:给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

解题思路

1、本来的思路为 一路向右 每次添加 根节点 以及其右孩子 以及右孩子的右孩子 如果右孩子的右孩子不存在 返回右孩子的左孩子,但是忽略了以下情况:第三层最右的元素不是接在上个最右元素的下面

2、正确思路为层序遍历的时候,根据size判断是否遍历到单层最后面的元素

代码实现

/*** 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; // 存放根节点 以及其对应的左右孩子vector<int>result;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();while(size--){TreeNode* node = que.front();que.pop();if(size==0)result.push_back(node->val); // 将每层最后一个元素放入resultif(node->left)que.push(node->left);if(node->right)que.push(node->right);  }}return result;}
};

题目链接:637.二叉树的层平均值

  • 题目描述:给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

解题思路

1、利用sum计算每层的和 注意精度!!! 无论是result 还是记录的sum 以及avr都要用 double

代码实现

/*** 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();int resize = size;vector<int>vec;double sum = 0;while(size--){TreeNode* node = que.front();que.pop();sum += (node->val);if(node->left)que.push(node->left);if(node->right)que.push(node->right);}double avr = sum/resize;result.push_back(avr);}return result;}
};

题目链接:429.N叉树的层序遍历

  • 题目描述:给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
  • 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

解题思路

1、N叉树中,一个节点有多个孩子,注意定义队列的类型不再是TreeNode* 而是Node*
2、在原来对于左右孩子的判断中,将节点孩子加入队列,节点孩子的数量为 children.size(),指针所对应的孩子为 node->children[i]

代码实现

/*
// 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;}
};
*/class Solution {public:vector<vector<int>> levelOrder(Node* root) {queue<Node*>que;vector<vector<int>>result;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();vector<int>vec;while(size--){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]);}}result.push_back(vec);}return result;}
};

题目链接:515.在每个树行中找最大值

  • 题目描述:给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

解题思路

1、定义maxnum为最小值INT32_MIN,因为-2^31 <= Node.val <= 2^31 - 1,有负数
2、注意条件运算符的用法 条件?满足条件返回值或运算:不满足返回值或运算

代码实现

/*** 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> largestValues(TreeNode* root) {queue<TreeNode*>que;vector<int>result;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();int maxnum = INT32_MIN;while(size--){TreeNode* node = que.front();que.pop();int num = node->val;maxnum =  maxnum<num ? num : maxnum;if(node->left)que.push(node->left);if(node->right)que.push(node->right);}result.push_back(maxnum);}return result;}
};

题目链接:116.填充每个节点的下一个右侧节点指针

  • 题目描述:给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
  • 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
  • 初始状态下,所有 next 指针都被设置为 NULL。

解题思路

1、在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点
2、每一层中,头部节点指针的next指向本层的下一个元素,本层的最后一个元素所对应的next指针为NULL
3、难点:定义一个Node* node , Node* nodepre ,在对于nodepre赋值时,记得要 node = nodepre, 为了之后对于node的左右孩子入队列。

代码实现

/*
// 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* node;Node* nodepre;for(int i=0;i<size;i++){if(i==0){nodepre = que.front(); // 头节点为nodepreque.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; // 最后一个节点指向NULL}return root;}
};

题目链接:117.填充每个节点的下一个右侧节点指针II

  • 题目描述:给定一个二叉树:
  • 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
  • 初始状态下,所有 next 指针都被设置为 NULL 。

解题思路

1、让这个指针指向其下一个右侧节点,与116的区别在于 此题说的是二叉树,但116给出的是完美二叉树,但逻辑不变

代码实现

/*
// 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* node;Node* nodepre;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;}
};

题目链接:111.二叉树的最小深度

  • 题目描述:给定一个二叉树,找出其最小深度。
  • 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
  • 说明:叶子节点是指没有子节点的节点。

解题思路

1、相对于层序遍历记录层数,增加判断条件:当该节点的左右孩子都为空的时候,说明遇到叶子节点。

代码实现

/*** 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 minDepth(TreeNode* root) {queue<TreeNode*>que;int mindep = 0;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();mindep++;TreeNode* node;while(size--){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 mindep;}}return mindep;}
};

题目链接:104.二叉树的最大深度

  • 题目描述:给定一个二叉树,找出其最大深度。
  • 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
  • 说明: 叶子节点是指没有子节点的节点。

解题思路

1、层序遍历模板题,记录层数

代码实现

/*** 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 depth = 0;if(root!=NULL)que.push(root);while(!que.empty()){int size = que.size();depth++;TreeNode* node;while(size--){node = que.front();que.pop();if(node->left)que.push(node->left);if(node->right)que.push(node->right);}}return depth;}
};

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

题目链接:LeetCode226.翻转二叉树

卡哥文解

视频讲解

  • 题目描述: 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

解题思路

  • 利用swap函数 把每个节点的左右孩子翻转
  • 注意:最后返回的值是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) {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;}
};

LeetCode 101. 对称二叉树

题目链接:101.对称二叉树

卡哥文解

视频讲解

  • 题目描述: 给你一个二叉树的根节点 root , 检查它是否轴对称。

解题思路

1、

实现难点

1、若用层序遍历 只判断 新存入的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:bool isSymmetric(TreeNode* root) {if(root==NULL)return true;queue<TreeNode*>que;que.push(root->left); // 左子树头节点que.push(root->right); // 右子树头节点while(!que.empty()){TreeNode* leftNode = que.front();que.pop();TreeNode* rightNode = que.front();que.pop();if(!leftNode && !rightNode)continue; // 左右节点都为空 说明对称// 左右一个节点不为空 或者都不为空但是数值不相等if(!leftNode || !rightNode ||(leftNode->val != rightNode->val)){ return false;}que.push(leftNode->left);que.push(rightNode->right);que.push(leftNode->right);que.push(rightNode->left);}return true;}
};

补充

NULL与 nullptr

  • C中NULL为(void*)0,C++中 NULL为整数0
  • C++11以后引入nullptr用以解决NULL在隐式转换和作为函数传入参数时的二义性问题
  • NULL存在二义性,既是整数也是一个指针
  • C语言中,void类型的变量可以赋值给任意类型的指针,也可以被任意类型的指针赋值。

day14总结复盘

1、了解层序遍历的模板之后,对于做以下题轻松很多
2、针对二叉树问题,解题时分清用前中后序遍历还是层序遍历。

代码随想录【day 14 二叉树】| 层序遍历 226.翻转二叉树 101.对称二叉树相关推荐

  1. 代码随想录算法训练营第十五天 | 102. 二叉树的层序遍历 | 226.翻转二叉树 | 101. 对称二叉树

    递归三部曲 确定递归函数的参数和返回值 确定终止条件 确定单层递归的逻辑 102. 二叉树的层序遍历 题解及想法 解法一 :递归法 class Solution {public List<Lis ...

  2. 二叉树层序遍历递归与非递归_二叉树的遍历「递归、非递归」以及自己的感受

    --------又来了一次二叉树的遍历,每次都有不一样的理解!真不知道那些大佬是如何想出这些牛逼的算法的,佩服至极!!!!大家多写,多想,对这些的理解真的会发生变化!!! -------- ----- ...

  3. 二叉树层序遍历递归与非递归_二叉树基础(1)-构建和遍历(递归和非递归)...

    二叉树的构建有2种方式:1.直接输入数字.2.根据两种顺序来判断另外一中顺序(后面会提到) 这里分享第一种构建方式,二叉树的前中后三种遍历方式(递归和非递归版本),和二叉树的层次遍历. 见代码demo ...

  4. 代码随想录算法训练营第十三天|102.二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

    链接:代码随想录 文章目录 102.二叉树的层序遍历 226.翻转二叉树 101.对称二叉树 解题方法 题目思路 示例代码 总结 解题思路 1.102.二叉树的层次遍历 解题思路 递归法,创立二维数组 ...

  5. 代码随想录算法训练营第十五天| 102层序遍历、226.翻转二叉树、101. 对称二叉树

    层序遍历 参考文章:代码随想录 解题思路: 层序遍历一个二叉树.就是从左到右一层一层的去遍历二叉树.这种遍历的方式和我们之前讲过的都不太一样. 需要借用一个辅助数据结构即队列来实现,队列先进先出,符合 ...

  6. 代码随想录算法训练营第十五天 | 层序遍历 10,226.翻转二叉树,101.对称二叉树 2

    代码随想录算法训练营第十五天 | 层序遍历 10,226.翻转二叉树,101.对称二叉树 2 1.1 层序遍历 10 1.1.1 102.二叉树的层序遍历 思路: 通过队列实现 class Solut ...

  7. 代码随想录算法训练营第15天,102.二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

    102.二叉树的层序遍历.226.反转二叉树.101.对称二叉树 102.二叉树的层序遍历 二叉树的层次遍历,我们可以定义一个队列, 当访问到某一个节点时,我们将它存在的左右节点放入队列中,便可达到按 ...

  8. 代码随想录算法训练营day15 | 102. 二叉树的层序遍历、226. 翻转二叉树、101. 对称二叉树

    102. 二叉树的层序遍历 class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {de ...

  9. 【LeetCode】专题一 二叉树层序遍历

    二叉树层序遍历 在本文中,我将会选取LeetCode上二叉树层序遍历的多道例题,并给出解答,通过多道题我们就可以发现,二叉树的层序遍历并不复杂,并且有着共通点. 102. 二叉树的层序遍历 给你二叉树 ...

最新文章

  1. Cocos2dx源码记录(1) CCGLProgram
  2. 多比矢量图开发手册(六)-Web高级图元编程
  3. apache负载均衡的安装和实现方法
  4. java 运算符表达式
  5. JSP userBean setProperty getProperty指令使用
  6. 国外persona用户画像_使用Mozilla Persona验证用户的指南
  7. 删除字符串的前置或者后置空格
  8. html加注算法源码,200种加密算法(源码)
  9. 排序算法之--归并排序(好玩的一个算法o。o)快速入门
  10. 爬虫-11-伪造电脑访问构建一个请求头
  11. 函数 写函数时需要:1明确这个功能的结果是什么? 2这个功能实现过程中是否需要未知内容参与运算?...
  12. ubuntu 查询cpu个数
  13. 使用Ps为图像批量制作水印
  14. Oracle EBS fnd_flex_ext.get_ccid返回CodeCombinationId为0
  15. 那些让面试官直呼内行的Java知识点(一)
  16. r语言中残差与回归值的残差图_用R语言做回归分析_iris数据集/longley数据集
  17. 秋招面经汇总(算法工程师,计算机视觉工程师,深度学习工程师,机器学习工程师)
  18. 问卷星简单自动填写调查问卷
  19. 我的世界服务器怎么使用无限附魔bug,我的世界惊现全新无限刷物品bug 服主大大都要注意了...
  20. 用户登录注册流程图-所有项目论文通用计算机毕业设计

热门文章

  1. XnView v2.13
  2. eclipse java 单步调试快捷键,Eclipse如何调试 Eclipse调试详细教程
  3. MongoDB Data Models 数据结构设计
  4. 京东用户购买意向预测(一)
  5. 测试人员如何保证测试质量
  6. 用计算机放光碟,怎么用电脑放光碟教?
  7. php动漫活动报名资源交流积分兑换系统
  8. 未来5年热门的10大就业方向,你处在哪个行业?
  9. 随着计算机网络的快速发展手机使用的普遍化,金标尺公考
  10. Object.key()