本文章为结合leetcode题目以及公众号“代码随想录”的文章所做的笔记!
感觉代码随想录的题目整理真的很好,比自己盲目刷题好很多。

目录

  • 1、二叉树小记
    • 1、满二叉树与完全二叉树
    • 2、二叉搜索树
    • 3、平衡二叉搜索树AVL
    • 4、二叉树存储方式
    • 5、二叉树遍历方式
    • 6、二叉树的定义
  • 2、二叉树深度优先遍历递归算法书写
    • 1、leetcode144题:
    • 2、leetcode145题:
    • 3、leetcode94题:
  • 3、二叉树深度优先遍历迭代算法书写
    • 1、先序遍历(迭代法)
    • 2、中序遍历(迭代法)
    • 3、后序遍历(迭代法)
  • 4、二叉树深度优先遍历迭代算法格式统一
  • 5、二叉树层序遍历
    • 1、leetcode102:二叉树的层序遍历
    • 2、leetcode107:二叉树的层序遍历 II
    • 3、leetcode199:二叉树的右视图
    • 4、leetcode637:二叉树的层平均值
    • 5、leetcode429:N叉树的层序遍历
    • 6、leetcode515. 在每个树行中找最大值
    • 7、leetcode116. 填充每个节点的下一个右侧节点指针
    • 8、leetcode117. 填充每个节点的下一个右侧节点指针 II(遇上一题思路代码一致)
    • 9、104. 二叉树的最大深度
    • 10、111. 二叉树的最大深度

1、二叉树小记

1、满二叉树与完全二叉树

满二叉树:深度为k,有2的k-1个节点的二叉树。
完全二叉树:除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第h层,则该层包含1~2h个节点。

2、二叉搜索树

二叉搜索树是有数值的,是一个有序树。
它的特点:

1、若它的左子树不空,则左子树所有结点的值均小于它根结点的值
2、若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
3、它的左右子树也分别为二叉排序树

3、平衡二叉搜索树AVL

AVL是一棵空数或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
C++中map、set、multimap、multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作时间复杂度都是logn。
而unordered_map、unordered_set、unordered_map、unordered_map底层实现是哈希表。

4、二叉树存储方式

链表存储与数组存储。
数组存储二叉树遍历:如果父节点的数组下标是i,那么它的左孩子就是i2+1,右孩子就是i2+2.

5、二叉树遍历方式

有两种遍历方式:
1、深度优先遍历:先往深走,遇到叶子结点再往回走
分为:前序遍历、中序遍历、后序遍历
这里的前中后,指的是中间结点的遍历顺序
前序遍历:中、左、右
中序遍历:左、中、右
后序遍历:左、右、中
深度优先遍历使用递归是比较方便的,可以借助栈使用非递归方式实现。

2、广度优先遍历:一层一层的去遍历
分为:层次遍历
广度优先遍历一般使用队列实现,利用了队列的先进先出的特点。这样才能一层一层的来遍历二叉树。

6、二叉树的定义

二叉树的定义和链表差不多,多了一个指针

struct TreeNode{int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x),left(NULL),right(NULL) {}
};

2、二叉树深度优先遍历递归算法书写

递归算法的三个要素:
1、确定递归函数的参数和返回值

若是在递归过程中需要处理某个参数,就在递归函数里面加上这个参数。
明确每次递归地返回值是什么,进而确定递归函数的返回类型

2、确定终止条件

1、如果在递归算法运行过程中出现栈溢出,大概率是终止条件写的不对
2、操作系统也是用一个栈的结构来保存每一层递归地信息,如果递归没有终止,操作系统的内存栈必然就会溢出

3、确定单层递归逻辑

确定每一层递归需要处理的信息。在这里也会重复调用自己来实现递归地过程

以前序遍历为例:
1、因为要打印出前序遍历结点的数值,所以参数里需要传入vector放在结点里的数据。没有返回值

void traversal(TreeNode* cur ,vector<int>& vec)

2、在递归过程中,如何算是递归结束?如果当前遍历的结点是空的,那么本层递归就结束了

if(cur == NULL) return;

3、前序遍历是中左右的循序,所以在单层递归中就要先取出中结点的数据

vec.push_back(cur->val);      //中
traversal(cur->left,vec);        //左
traversal(cur->right,vec);       //右

完整代码:

class Solution{public:void traversal(TreeNode* cur , vector<int>& vec){if(cur == NULL) return;vec.push_back(cur->val);traversal(cur->left,vec);traversal(cur->right,vec);}vector<int> preorderTraversal(TreeNode* root){vector<int> result;traversal(root,result);return result;}
};

中序遍历:

void traversal(TreeNode* cur , vector<int>& vec)
{if(cur == NULL) return;traversal(cur->left,vec);vec.push_back(cur->val);traversal(cur->right,vec);
}

后序遍历:

void traversal(TreeNode* cur , vector<int>& vec)
{if(cur == NULL) return;traversal(cur->left,vec);traversal(cur->right,vec);vec.push_back(cur->val);
}

1、leetcode144题:

给定一个二叉树,返回它的 前序 遍历。
示例:
输入: [1,null,2,3]
1

2
/
3
输出: [1,2,3]

/*** 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:void traversal(TreeNode* cur , vector<int>& vec){if(cur == NULL) return;vec.push_back(cur->val);traversal(cur->left,vec);traversal(cur->right,vec);}vector<int> preorderTraversal(TreeNode* root){vector<int> result;traversal(root,result);return result;}
};

2、leetcode145题:

给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [1,null,2,3]
1

2
/
3
输出: [3,2,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:void traversal(TreeNode* cur , vector<int>& vec){if(cur == NULL) return;traversal(cur->left,vec);traversal(cur->right,vec);vec.push_back(cur->val);}vector<int> postorderTraversal(TreeNode* root) {vector<int> result;traversal(root,result);return result;}
};

3、leetcode94题:

/*** 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:void traversal(TreeNode* cur , vector<int>& vec){if(cur == NULL) return;traversal(cur->left,vec);vec.push_back(cur->val);traversal(cur->right,vec);}vector<int> inorderTraversal(TreeNode* root) {vector<int> result;traversal(root,result);return result;}
};

3、二叉树深度优先遍历迭代算法书写

原理:为什么可以使用迭代法(非递归地方式)来实现二叉树的前后中序遍历?
递归地实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,
然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

1、先序遍历(迭代法)

前序遍历:中左右;每次处理的是中间结点,先将根结点放入栈中,然后将右孩子放入栈中,再加入左孩子。
为什么要先加入有孩子,再加入左孩子?
这样出栈的时候才是中左右的顺序。
顺序如下:

class Solution{public:vector<int> preorderTraversal(TreeNode* root){stack<TreeNode*> st;       //构建一个栈vector<int> result;st.push(root);          //先将根结点压入栈中while(!st.empty()){          //当栈中还有元素时TreeNode* node = st.top();   //将栈顶元素赋给新结点    st.pop();                   //将栈顶元素出栈if(node !=NULL) result.push_back(node->val);   //如果这个结点不为空,将值赋给resultelse continue;                                 //否则继续,(也就是说如果结点为空不赋值)st.push(node->right);     //将该中结点的右孩子压入栈中st.push(node->left);      //将该结点中的左孩子压入栈中}return result;}
};

2、中序遍历(迭代法)

注意,前序遍历的迭代法思路不能直接套用到中序遍历上。
在迭代的过程中有两个操作:
1、【处理】将元素放入result数组
2、【访问】遍历结点
前序遍历中:遍历的顺序是中左右。
先访问中间结点,先处理中间结点
要访问的元素和要处理的元素的顺序一致,都是中间结点。
而中序遍历,遍历顺序为左中右。
先访问二叉树顶部结点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理结点(再把结点的数值放到result数组中);
这就导致了处理顺序和访问顺序不一致
所以在使用迭代 法时,需要借用指针的遍历来帮助访问结点,使用栈来处理结点上的元素。

class Solution{public:vector<int> inorderTraversal(TreeNode* root){vector<int> result;stack<TreeNode*> st;TreeNode* cur = root;while(!st.empty() || cur!=NULL){if(cur!=NULL){st.push(cur);cur = cur->left;    //先一直都是从左结点深入,直到某一个结点的左孩子为NULL}//如果该点是父结点的左孩子,且指向空,则将cur指向它的父结点(为最深的左结点),然后将父结点出栈,将值赋给结果数组,再将指针指向此父结点的右孩子(这样保证了左中右的遍历顺序)else{cur = st.top();st.pop();result.push_back(cur->val);cur = cur->right;}          }return result;}
};

3、后序遍历(迭代法)

后序遍历:左右中。
先序遍历:中左右。
我们只需要调整一下先序遍历的代码顺序,变为中右左的遍历顺序。
然后反转result数组,输出结果就是左右中。

/*** 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> postorderTraversal(TreeNode* root) {stack<TreeNode*> st;     //构建一个栈vector<int> result;st.push(root);          //先将根结点压入栈中while(!st.empty()){          //当栈中还有元素时TreeNode* node = st.top();   //将栈顶元素赋给新结点    st.pop();                   //将栈顶元素出栈if(node !=NULL) result.push_back(node->val);   //如果这个结点不为空,将值赋给resultelse continue;                                 //否则继续,(也就是说如果结点为空不赋值)st.push(node->left);      //将该中结点的左孩子压入栈中st.push(node->right);     //将该结点中的右孩子压入栈中}//反转resultreverse(result.begin(),result.end());return result;}
};

4、二叉树深度优先遍历迭代算法格式统一

之前迭代法例子中提到无法同时解决访问节点(遍历)和处理结点(将结点放入结果)不一致的情况。
解决方法:
将访问的结点放入栈中,把要处理的结点也放入栈中,但是要做标记
标记方法:将要处理的结点放入栈中之后,紧接着放入一个空指针作为标记
将访问的结点直接加入到栈中,但是如果是处理的结点则后面放入一个空结点,这样只有空结点弹出的时候才将下一个结点放进结果集。
如何知道该访问的结点是我们需要处理的结点?(中结点是我们需要处理的结点),所以只需要在中结点后面加入一个空结点就行了
中序遍历:

class Solution{public:vector<int> inorderTraversal(TreeNode* root){vector<int> result;stack<TreeNode*> st;if(root !=NULL) st.push(root);while(!st.empty()){TreeNode* node = st.top();  //标记操作,直到遇到NULLif(node!=NULL){//将该结点弹出,避免重复操作st.pop();//添加右结点if(node->right) st.push(node->right);//添加中结点st.push(node);//标记st.push(NULL); //添加左结点if(node->left) st.push(node->left);}//只有遇到空结点的时候,才将下一个结点放入到结果中else{//弹出空结点st.pop();node = st.top();st.pop();   result.push_back(node->val);}}return result;}
};

先序遍历:中左右

class Solution{public:vector<int> preorderTraversal(TreeNode* root){vector<int> result;stack<TreeNode*> st;if(root !=NULL) st.push(root);while(!st.empty()){TreeNode* node = st.top();  //标记操作,直到遇到NULLif(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();   result.push_back(node->val);}}return result;}
};

后序遍历:左右中

class Solution{public:vector<int> postorderTraversal(TreeNode* root){vector<int> result;stack<TreeNode*> st;if(root !=NULL) st.push(root);while(!st.empty()){TreeNode* node = st.top();  //标记操作,直到遇到NULLif(node!=NULL){//将该结点弹出,避免重复操作st.pop();//添加中结点st.push(node);//标记st.push(NULL); //添加右结点if(node->right) st.push(node->right);//添加左结点if(node->left) st.push(node->left);}//只有遇到空结点的时候,才将下一个结点放入到结果中else{//弹出空结点st.pop();node = st.top();st.pop();   result.push_back(node->val);}}return result;}
};

总结:

这种方法比较好记忆,主要注意以下几点
1、栈的特性入栈和出栈相反,所以如果想输出顺序为“左中右”,入栈顺序必须为“右中左”
2、入栈的处理:可以将整个树简化为3个结点一组的多个子树。每次循环处理的实际就是将这样的3个结点按照规定的顺序进行入栈。
3、NULL结点的加入以及出栈规则的指定:
以中序遍历为例,保证了当左孩子作为栈顶元素时不会立即出栈,而是会将当前的左孩子(栈顶元素)作为下次遍历的父结点;接着按照规则顺序入栈,直到当前的左孩子作为父结点再无孩子时(此时是入栈规则为父结点、NULL结点),遇到NULL结点,进行出栈。

5、二叉树层序遍历

1、leetcode102:二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其层次遍历结果:

[
[3],
[9,20],
[15,7]
]
思考:
借用队列来实现,【队列先进先出,符合一层一层遍历的逻辑】
而栈先进后出适合模拟深度优先遍历也就是递归地逻辑。
【这种层序遍历的方式就是图论中的广度优先遍历,只不过用在了二叉树上】
思考:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
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;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列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;}
};

2、leetcode107:二叉树的层序遍历 II

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其自底向上的层次遍历为:

[
[15,7],
[9,20],
[3]
]
思路:在层序遍历的基础上进行直接反转

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:vector<vector<int>> levelOrderBottom(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;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列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);}//将层序遍历反转一下结果reverse(result.begin(),result.end());return result;}
};

3、leetcode199:二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <—
/
2 3 <—
\
5 4 <—
思路:对层序遍历的的结果的每个子层result取最后的一个,作为结果返回。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);vector<int> realresult;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();vector<int> vec;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列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);}realresult.push_back(vec[size-1]);}return realresult;}
};

4、leetcode637:二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
示例 1:
输入:
3
/
9 20
/
15 7
输出:[3, 14.5, 11]
解释:
第 0 层的平均值是 3 , 第1层是 14.5 , 第2层是 11 。因此返回 [3, 14.5, 11] 。
提示:
节点值的范围在32位有符号整数范围内。

思考:层序遍历中加入累加以及求均值操作

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:vector<double> averageOfLevels(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);vector<double> realresult;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();vector<int> vec;double sum = 0;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();vec.push_back(node->val);sum+=vec[i];//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}realresult.push_back(sum /size);}return realresult;}
};

5、leetcode429:N叉树的层序遍历

给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
例如,给定一个 3叉树 :
返回其层序遍历:
[
[1],
[3,2,4],
[5,6]
]
说明:
树的深度不会超过 1000。
树的节点总数不会超过 5000。
思考:与二叉树层序遍历方法一样,不过子结点的个数不定

/*
// 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;if(root!=NULL) que.push(root);vector<vector<int>> result;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();vector<int> vec;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列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;}
};

6、leetcode515. 在每个树行中找最大值

您需要在二叉树的每一行中找到最大的值。
示例:
输入:
1
/
3 2
/ \ \
5 3 9

输出: [1, 3, 9]
思考:层序遍历,然后在每层中找最大值

/*** 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;if(root!=NULL) que.push(root);vector<int> result;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();int max=-2147483648;    //(最小值)vector<int> vec;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();vec.push_back(node->val);if(max<=node->val) max = node->val;//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}result.push_back(max);}return result;}
};

7、leetcode116. 填充每个节点的下一个右侧节点指针

给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。

示例:


解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。
提示:
你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

思考:层序遍历,只不过在单层遍历的时候记录本层的头部节点,然后在遍历的时候让前一个节点指向本节点。

/*
// 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* Prenode;for(int i =0;i<size;i++){//每层第一个元素元素if(i==0){Prenode =que.front();que.pop();node = Prenode;}//非每层第一个结点else{node = que.front();que.pop();//将此结点与上一个结点连在一起Prenode->next = node;Prenode = node; }//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}Prenode->next =NULL;}return root;}
};

8、leetcode117. 填充每个节点的下一个右侧节点指针 II(遇上一题思路代码一致)

给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。

进阶:
你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

9、104. 二叉树的最大深度

思路:层序遍历,每层对一个变量++即可
给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回它的最大深度 3 。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:int maxDepth(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);int result=0;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列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);}result++;}return result; }
};

10、111. 二叉树的最大深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回它的最小深度 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:int minDepth(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);int result=0;int break_flag=0;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();if(!node->left && !node->right){return result+1;} //将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}result++;}return result;  }
};

二叉树笔记(深度遍历与广度遍历+13道leetcode题目(深度3道、广度10道))相关推荐

  1. MySQL数据库-笔记03【范式(1NF、2NF、3NF)、查询练习题*10道(附解析)】

    学习地址:一天学会 MySQL 数据库      MySQL安装教程      MySQL专栏

  2. 【代码随想录训练营】【Day14】第六章|二叉树|理论基础|递归遍历|迭代遍历|统一迭代

    理论基础 二叉树的定义形式有:节点指针和数组 在数组中,父节点的下标为i,那么其左孩子的下标即i*2+1,右孩子的下标即为i*2+2 二叉树的常见遍历形式有:前序遍历.后序遍历.中序遍历和层序遍历 前 ...

  3. 二叉树层次遍历--广度遍历和深度遍历

    问题来源:二叉树层次遍历 问题描述:给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点). 例子: 给定二叉树: [3,9,20,null,null,15,7], 3/ \9 ...

  4. 对称二叉树--深度遍历与广度遍历

    问题来源:对称二叉树 问题描述:给定一个二叉树,检查它是否是镜像对称的. 比如,下面这个二叉树是镜像对称的: 1 / 2 2 / \ / 3 4 4 3 而这个二叉树则不是镜像对称的. 1 / 2 2 ...

  5. 数据结构与算法之二叉树广度遍历、深度遍历总结

    什么是树,它是和链表一样都是一种抽象数据类型(ADT),包括数据结构和对数据的操作. 树是一种二维平面的数据结构结构,它也是由节点组成的,只是它的后继节点不止一个,而链表的后继节点只有一个. 树具有以 ...

  6. 树与树算法二叉树的层次遍历/广度遍历/深度遍历详解与代码实现

    一. 树与树算法 1.1树的概念   树(tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>=1)个有限节点组成一个具有 ...

  7. 数据结构【图】—022邻接矩阵的深度和广度遍历

    1 #include "000库函数.h" 2 //无向图 3 4 typedef char VertexType; /* 顶点类型应由用户定义 */ 5 typedef int ...

  8. 数据结构——无向图创建邻接表以及深度遍历、广度遍历(C语言版)

    摘自:数据结构--无向图创建邻接表以及深度遍历.广度遍历(C语言版) 作者:正弦定理 发布时间:2020-12-22 20:55:12 网址:https://blog.csdn.net/chinese ...

  9. 数据结构【图】—023邻接表深度和广度遍历

    1 #include "000库函数.h" 2 //无向图 3 4 #define MAXSIZE 9 /* 存储空间初始分配量 */ 5 #define MAXEDGE 15 6 ...

最新文章

  1. 背包问题(Knapsack problem)采用动态规划求解
  2. linux去重文件第一列,科学网—Linux实用命令 - 刘洪波的博文
  3. 浅谈SAP CRM开发——技术概念、与ECC 系列产品区别
  4. cross_compile = arm-linux-,cross compile grpc for arm
  5. python 编写简单网页服务器
  6. OpenShift 4之唤醒休眠的OpenShift应用
  7. 大型油烟机清洗机器人_大型油烟机清洗机
  8. 对于文章的字母、单词、短语,(无用词表)的检索Java代码实现
  9. leetcode——给定一个整数数组和一个目标值返回两个数字对应的索引,使得这两个数字之和等于目标值
  10. paip.TechExcel DevSuite IIS 根目录结构
  11. windows时间设置
  12. 深度学习赋能侧信道攻击
  13. python实现黑客帝国动画效果
  14. CAD:计算三角形的外接圆圆心
  15. springcloud微服务学习笔记(四十五):Gateway9527搭建
  16. 【第104期】游戏策划:如何看待另一半沉迷游戏?
  17. chrome边解析Html边显示,谷歌浏览器插件侧边翻译Edge Translate
  18. 【华为机试】【校招】【Java】机器人走迷宫(DFS)
  19. Android车机初体验
  20. 在word2016中对图片插入题注

热门文章

  1. 【APICloud系列|9】APICloud自定义APPloader一个月未更新,快速更新的办法
  2. 扬州大学计算机考研难考吗,扬州大学(专业学位)计算机技术考研难吗
  3. 在计算机网络中可用于信息传输的介质,在计算机网络中,双绞线、同轴电缆及光纤等用于传输信息的载体被称为______介质。...
  4. mysql 8.0认证失败_解决mysql8.0因密码认证插件导致的链接不上
  5. 投影元素直接隔离_摸着夜色上露台开投影,是巴塞罗那设计师的浪漫
  6. h1、h2、h3标签及strong标签对页面seo的影响
  7. 浏览器滚动条 --- 自定义“衣裳”
  8. 博客园如何使用MarkDown
  9. noip模拟赛 写代码
  10. 关于OPENSSL的使用