DAY18
二叉树的层序遍历
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>> levelOrder(TreeNode* root) {
- queue<TreeNode*> que;
- vector<vector<int>> result;
- if(root!=nullptr) que.push(root);
- 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;
- }
- };
二叉树层序遍历递归模版:
- /**
- * 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 order(TreeNode* node,vector<vector<int>> &result,int depth)
- {
- if(node==nullptr) return;
- if(result.size()==depth) result.push_back(vector<int>());
- result[depth].push_back(node->val);
- if(node->left) order(node->left,result,depth+1);
- if(node->right) order(node->right,result,depth+1);
- }
- vector<vector<int>> levelOrder(TreeNode* root) {
- vector<vector<int>> result;
- int depth=0;
- order(root,result,depth);
- return result;
- }
- };
107二叉树的层序遍历II
递归法模版:
- /**
- * 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 order(TreeNode* node,vector<vector<int>> &result,int depth)
- {
- if(node==nullptr) return;
- if(result.size()==depth) result.push_back(vector<int>());
- result[depth].push_back(node->val);
- if(node->left) order(node->left,result,depth+1);
- if(node->right) order(node->right,result,depth+1);
- }
- vector<vector<int>> levelOrderBottom(TreeNode* root) {
- vector<vector<int>> result;
- int depth=0;
- order(root,result,depth);
- reverse(result.begin(),result.end());
- return 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<vector<int>> levelOrderBottom(TreeNode* root) {
- vector<vector<int>> result;
- queue<TreeNode*> que;
- if(root!=nullptr) que.push(root);
- 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);
- }
- reverse(result.begin(),result.end());
- return result;
- }
- };
199二叉树的右视图
现在变成一维vector的return result,该怎么写递归的模版呢?递归似乎更麻烦了。
先试试普通方法:
不行,思路错了:不能只遍历根节点和右孩子,因为会出现这种:
加了一句else if();新的问题又出现了:....
有想法了(“不如把思路逆转过来!”):正常层序遍历,vector<vector<int>> result的每行,取最后一列,就是答案。怎么写语法呢?看答案吧:
代码随想录的思路要更直接:判断是否遍历到单层的最后面的元素,如果是,就放进result数组里,随后返回result就可以了。
那么如何知道“是否遍历到单层的最后面的元素”呢?我们有que.size()来记录这层树的节点个数!i 是节点的指针,那么i==size-1的话,就是答案;push_back.
- /**
- * 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> res;
- if(root!=nullptr) que.push(root);
- while(!que.empty())
- {
- int size=que.size();
- for(int i=0;i<size;i++)
- {
- TreeNode* node=que.front();
- que.pop();
- if(i==size-1) res.push_back(node->val);
- if(node->left) que.push(node->left);
- if(node->right) que.push(node->right);
- }
- }
- return res;
- }
- };
637二叉树的层平均值
语法怎么写
在层外和层里面操作就好啦:也就是:for里面和for外面。灵活一点!
数据上没有为难人,写好就通过了:
- /**
- * 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> res;
- if(root!=nullptr) que.push(root);
- while(!que.empty())
- {
- int size=que.size();
- double sum=0;
- for(int i=0;i<size;i++)
- {
- TreeNode* node=que.front();
- que.pop();
- sum+=node->val;
- if(node->left) que.push(node->left);
- if(node->right) que.push(node->right);
- }
- res.push_back(sum/size);
- }
- return res;
- }
- };
牢记:有size来记录每层节点数量。
429 N叉树的层序遍历
Node的孩子不为空的时候,push_back就好,语法怎么写,尤其是这个children的迭代。。
哦:node->children[i]。因为它是一个vector,进一步,用for来迭代。记住for里面有个for,逻辑。
- /*
- // 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) {
- vector<vector<int>> res;
- queue<Node*> que;
- if(root!=nullptr) que.push(root);
- 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++)
- {
- que.push(node->children[j]);
- }
- }
- res.push_back(vec);
- }
- return res;
- }
- };
515在每个树行中找最大值
最大的int怎么写?INT32_MAX;过不了,初始化的num不够小。
初始化:不要num=-1*INT32_MAX;要:num=INT_MIN.
可能是因为这个:
- /**
- * 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) {
- vector<int> res;
- queue<TreeNode*> que;
- if(root!=nullptr) que.push(root);
- while(!que.empty())
- {
- int num=INT_MIN;
- int size=que.size();
- for(int i=0;i<size;i++)
- {
- TreeNode* node=que.front();
- que.pop();
- num=max(num,node->val);
- if(node->left) que.push(node->left);
- if(node->right) que.push(node->right);
- }
- res.push_back(num);
- }
- return res;
- }
- };
116填充每个节点的下一个右侧节点指针
怎么写,他要返回什么,怎么把next这个信息穿回去呢?
接上,为什么对node=que.front操作,return root就是答案?把root、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!=nullptr) que.push(root);
- while(!que.empty())
- {
- Node* nodepre;
- Node* node;
- int size=que.size();
- for(int i=0;i<size;i++)
- {
- //i是节点的指针,所以这里用i来写if
- if(i==0){
- nodepre=que.front();
- que.pop();
- node=nodepre;//勿漏
- }
- else{
- node=que.front();//更新node
- que.pop();
- nodepre->next=node;//key
- //不要忘了更新nodepre,nodepre的作用:记录当前节点(node)的上一个节点
- nodepre=nodepre->next;
- }
- if(node->left) que.push(node->left);
- if(node->right) que.push(node->right);
- }
- nodepre->next=nullptr;
- }
- return root;
- }
- };
117填充每个节点的下一个右侧节点指针II
只要彻底理解了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!=nullptr) 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=nullptr;
- }
- return root;
- }
- };
104二叉树的最大深度
简单:
- /**
- * 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;
- if(root!=nullptr) que.push(root);
- int res=0;
- while(!que.empty())
- {
- int 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);
- }
- res++;
- }
- return res;
- }
- };
111二叉树的最小深度
暂时没思路。再想想:左右孩子都为空,则说明到了最低点。
- /**
- * 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 depth=0;
- if(root!=nullptr) que.push(root);
- while(!que.empty())
- {
- depth++;
- int 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);
- if(node->left==nullptr && node->right==nullptr) return depth;
- }
- }
- return depth;
- }
- };
226翻转二叉树
交换指针竟然可以直接用swap来做。
前序版本:
- /**
- * 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* invertT(TreeNode* root)
- {
- if(root==nullptr) return root;
- swap(root->left,root->right);
- if(root->left) invertT(root->left);
- if(root->right) invertT(root->right);
- return root;
- }
- TreeNode* invertTree(TreeNode* root) {
- return invertT(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* invertT(TreeNode* root)
- {
- if(root==nullptr) return root;
- if(root->left) invertT(root->left);
- if(root->right) invertT(root->right);
- swap(root->left,root->right);
- return root;
- }
- TreeNode* invertTree(TreeNode* root) {
- return invertT(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*> stk;
- if(root!=nullptr) stk.push(root);
- while(!stk.empty())
- {
- TreeNode* node=stk.top();
- stk.pop();
- swap(node->left,node->right);
- if(node->left) stk.push(node->left);
- if(node->right) stk.push(node->right);
- }
- return root;
- }
- };
101对称二叉树
需要收集孩子的信息,并向上一级(某个根节点)返回这些信息时候,用后序遍历。
- /**
- * 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==nullptr&&right==nullptr) return true;
- else if(left==nullptr&&right!=nullptr) return false;
- else if(left!=nullptr&&right==nullptr) return false;
- else if(left->val!=right->val) return false;
- // 此时就是:左右节点都不为空,且数值相同的情况.这时候才可以接着往下走,递归
- // 此时才做递归,做下一层的判断
- //不接着写else if了
- bool outside=compare(left->left,right->right);
- bool inside=compare(left->right,right->left);
- bool res=outside&&inside;
- return res;
- }
- bool isSymmetric(TreeNode* root) {
- return compare(root->left,root->right);
- }
- };
对称二叉树的推荐题目:
100相同的树
- /**
- * 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 iscom(TreeNode* p,TreeNode*q)
- {
- if(p==nullptr&&q==nullptr) return true;
- else if(p!=nullptr&&q==nullptr) return false;
- else if(p==nullptr&&q!=nullptr) return false;
- else if(p->val!=q->val) return false;
- bool o=iscom(p->left,q->left);
- bool i=iscom(p->right,q->right);
- bool res=i&&o;
- return res;
- }
- bool isSameTree(TreeNode* p, TreeNode* q) {
- return iscom(p,q);
- }
- };
572另一棵树的子树
怎么下手呢?
力扣官方解法:深度优先搜索暴力匹配。
判断t是否和树s的任意子树相等。即:
判断s的每个子节点是否和t相等。3个条件,与的关系:
- 当前两个树的根节点的值是否相等
- 并且,s的左子树和t的左子树是否相等
- 并且,s的右子树和t的右子树是否相等
判断t是否为s的子树的三个条件,是或的关系:
- 当前两棵树相等
- 或者,t是s的左子树
- 或者,t是s的右子树
图片来自力扣官方题解
- /**
- * 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:
- //dfs搜到之后,开始检查两个子树是否相等
- bool check(TreeNode*o,TreeNode*t)
- {
- if(o==nullptr&&t==nullptr) return true;
- if((o!=nullptr&&t==nullptr)||(o==nullptr&&t!=nullptr)||(o->val!=t->val)) return false;
- return (check(o->left,t->left) &&check(o->right,t->right));
- }
- //搜哪个是大子树里相等子树的根节点
- bool dfs(TreeNode* o,TreeNode* t)
- {
- if(o==nullptr) return false;
- //下一句一定要注意,是先o,t;前序遍历。注意逻辑,对当前遍历节点用check,需要递归时候,调用的是dfs
- return check(o,t)||dfs(o->left,t) ||dfs(o->right,t);
- }
- bool isSubtree(TreeNode* root, TreeNode* subRoot) {
- return dfs(root,subRoot);
- }
- };
结束!明天早起,注意效率。