基础算法精讲 13 | 二叉树的层序遍历
102. 二叉树的层序遍历
思路
- 如何层次遍历?
用队列.
TreeNode* tmpSwitch= q.front(); q.pop();记录一个就弹出一个,只是迭代更新用。
while (!q.empty()) {//把q中pop出去,用tmp接受需要有一个中间值帮忙。TreeNode* tmpSwitch= q.front();q.pop();tmpLevel.push_back(tmpSwitch->val);if (tmpSwitch->left != nullptr) q.push(tmpSwitch->left);if (tmpSwitch->right != nullptr) q.push(tmpSwitch->right); }
- 如何实现分层效果?
vector tmp 和 for(int i = que.size(); i > 0; - -i)
计算一次队列中的个数,就计算过的结点 放入tmp容器中。
for(int i = q.size(); i > 0; --i) {tmpSwitch = q.front();q.pop();tmpLevel.push_back(tmpSwitch->val);... ...}res.push_back(tmp);
- 3个记忆点。queue<TreeNode*>,vectortmpLevel,TreeNode* vector<vector> res。其中
queue,tmp两个容器来回倒腾就好。 - 特例处理: 当根节点为空,则返回空列表 [ ] 。
if(root==nullptr)return res;
完整代码
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> q;vector<vector<int>> res;if(root==nullptr)return res;//2.开始干活了q.push(root);while(!q.empty()){vector<int> tmpLevel;for(int i=q.size();i>0;i--){TreeNode* tmpSwitch = q.front();q.pop();tmpLevel.push_back(tmpSwitch->val);if(tmpSwitch->left!=nullptr) q.push(tmpSwitch->left);if(tmpSwitch->right!=nullptr)q.push(tmpSwitch->right);}res.push_back(tmpLevel);}return res;}
};
103. 二叉树的锯齿形层序遍历
思路
- 层序遍历
- 将分层输入的tmpLevel翻转一下啊
if(count%2==1)reserver(tmpLevel);//把vector翻转void reserver(vector<int>& v){int l = 0;int r=v.size()-1;//【 )左闭右开while(l<r){int tmp=v[l];v[l]=v[r];v[r]=tmp;l++;r--;}}
完整代码
class Solution {
public://把vector翻转void reserver(vector<int>& v){int l = 0;int r=v.size()-1;//【 )左闭右开while(l<r){int tmp=v[l];v[l]=v[r];v[r]=tmp;l++;r--;}}vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> res;queue<TreeNode*> q;int count=0;if(root==nullptr) return res;q.push(root);while(!q.empty()){vector<int> tmpLevel;for(int i=q.size();i>0;i--){TreeNode* tmpSwith= q.front();q.pop();tmpLevel.push_back(tmpSwith->val);if(tmpSwith->left!=nullptr) q.push(tmpSwith->left);if(tmpSwith->right!=nullptr) q.push(tmpSwith->right);}if(count%2==1)reserver(tmpLevel);count++;res.push_back(tmpLevel);}return res;}
};
513. 找树左下角的值
思路
- 层序遍历
- 将
vector<vector<int>> res换成int res。并且加一个判断,如果是该层次遍历的第一个结点,就用res记录这个。这样每次一层的for遍历结束都会覆盖前一层的res。最后的res就是左下角的值。
经典的错误
class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> q;int res=0;// if(root==nullptr) // return res;q.push(root);while(!q.empty()){for(int i=q.size();i>0;i--){TreeNode* tmp = q.front();q.pop();//经典的错误,q.size()是随q.pop()更新的if(i==q.size()) res=tmp->val;if(tmp->left) q.push(tmp->left);if(tmp->right) q.push(tmp->right);} }return res;}
};
完整代码
class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> q;int res=0;// if(root==nullptr) // return res;q.push(root);while(!q.empty()){int size= q.size();for(int i=size ; i>0 ; i--){TreeNode* tmp = q.front();q.pop();if(i==size) res=tmp->val;if(tmp->left) q.push(tmp->left);if(tmp->right) q.push(tmp->right);} }return res;}
};
107. 二叉树的层序遍历 II
思路
- 层次遍历
- 再将vector<vector> res 翻转哈哈哈
- 有一个很致命的点就是
vector<int> level是辅助分层的,要定义在while中,不能定义在整个函数中。
完整代码
class Solution {
public:void reverse( vector<vector<int>>& v){int l = 0;int r = v.size()-1;while(l<r){vector<int> tmp = v[l];v[l] = v[r];v[r] = tmp;l++;r--;}}vector<vector<int>> levelOrderBottom(TreeNode* root) {vector<vector<int>> res;queue<TreeNode*> q;if(root==nullptr) return res;//开始层序遍历q.push(root);while(!q.empty()){ vector<int> level; int size = q.size();for(int i=size;i>0;i--){TreeNode* tmp=q.front();q.pop();level.push_back(tmp->val);if(tmp->left!=nullptr) q.push(tmp->left);if(tmp->right!=nullptr) q.push(tmp->right); }res.push_back(level);}reverse(res);return res;}
};
104. 二叉树的最大深度
111. 二叉树的最小深度
116. 填充每个节点的下一个右侧节点指针
思路
- 依旧应用了层数遍历。
- 在层序遍历的分层for中,将结点node串了起来。因为是队列,不能随机访问,所以就串一个pop一个
for(int i =0;i<size;i++){Node* cur = q.front();q.pop();if(i>0){pre->next = cur;}pre= cur;... ...}
完整代码
class Solution {
public:Node* connect(Node* root) {//Node* res;if(root==nullptr) return nullptr;queue<Node*> q;q.push(root);while(!q.empty()){Node* pre =nullptr;int size= q.size();for(int i =0;i<size;i++){Node* cur = q.front();q.pop();if(i>0){pre->next = cur;}pre= cur;if(cur->left) q.push(cur->left);if(cur->right) q.push(cur->right);}} return root; }
};
117. 填充每个节点的下一个右侧节点指针 II
思路
用bfs的话,就与上一题没有任何区别了
1302. 层数最深叶子节点的和
递归中的操作型
class Solution {
public:int maxLevel =-1;int depth = 0;int res = 0;void tra(TreeNode* t){if(t==nullptr) return;depth++;if(depth> maxLevel){maxLevel=depth;res=t->val;}//这里不能写if(depth == maxLevel),经典的错误else if(depth == maxLevel){res+=t->val;}tra(t->left);tra(t->right);depth--;}int deepestLeavesSum(TreeNode* root) {tra(root);return res;}
};
BFS
已经碰到过很多次sumLevel的这种用法了。每一层我都计数,但是我一直会被覆盖。所以我记录的就是最后一层。
class Solution {
public:int deepestLeavesSum(TreeNode* root) {queue<TreeNode*> q;q.push(root);//定义sumLevelint sumLevel=0;while(!q.empty()){int size=q.size();//这里只是重新赋值,不是重新定义sumLevel = 0;for(int i =0;i<size;i++){TreeNode* tmp =q.front();q.pop();sumLevel+=tmp->val;if(tmp->left) q.push(tmp->left);if(tmp->right) q.push(tmp->right);}}return sumLevel;}
};
