二叉树层序遍历
如果说前序和后序遍历是所谓的深度优先遍历,那么层序遍历便是广度优先遍历了。使用的是队列而不是栈。而如果要使用递归的话需要记录当前回溯节点的深度。
102.二叉树的层序遍历
https://leetcode.cn/problems/binary-tree-level-order-traversal/
递归
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*> que;
if (root) que.push(root);
int len;
while (!que.empty()) {
len = que.size();
vector<int> tmp;
for (int i = 0; i < len; i++) {
tmp.push_back(que.front()->val);
if (que.front()->left) que.push(que.front()->left);
if (que.front()->right) que.push(que.front()->right);
que.pop();
}
result.push_back(tmp);
}
return result;
}
};
迭代
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*> que;
if (root) que.push(root);
int len;
while (!que.empty()) {
len = que.size();
vector<int> tmp;
for (int i = 0; i < len; i++) {
tmp.push_back(que.front()->val);
if (que.front()->left) que.push(que.front()->left);
if (que.front()->right) que.push(que.front()->right);
que.pop();
}
result.push_back(tmp);
}
return result;
}
};
107.二叉树的层次遍历 II
https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/
从最底层子叶节点遍历到根节点,只需要将遍历结果翻转即可。
递归
class Solution {
public:
void order2(TreeNode* cur, vector<vector<int>>& result, int depth) {
if (!cur) return;
if (result.size() == depth) result.push_back(vector<int>{});
result[depth].push_back(cur->val);
if (cur->left) order2(cur->left, result, depth + 1);
if (cur->right) order2(cur->right, result, depth + 1);
}
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> result;
order2(root, result, 0);
reverse(result.begin(), result.end());
return result;
}
};
199.二叉树的右视图
https://leetcode.cn/problems/binary-tree-right-side-view/
层序遍历时只记录最右节点即可。
(采用从右遍历到左的做法,这样只要记录每一层的第一个节点就是最右节点)
递归
class Solution {
public:
void righSide(TreeNode* cur, vector<int>& result, int depth) {
if (!cur) return;
if (result.size() == depth) result.push_back(cur->val);
if (cur->right) righSide(cur->right, result, depth + 1);
if (cur->left) righSide(cur->left, result, depth + 1);
}
vector<int> rightSideView(TreeNode* root) {
vector<int> result;
righSide(root, result, 0);
return result;
}
};
迭代
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> result;
queue<TreeNode*> que;
if (root) que.push(root);
while (!que.empty()) {
result.push_back(que.front()->val);
int len = que.size();
while (len--) {
if (que.front()->right) que.push(que.front()->right);
if (que.front()->left) que.push(que.front()->left);
que.pop();
}
}
return result;
}
};
637.二叉树的层平均值
https://leetcode.cn/problems/average-of-levels-in-binary-tree/
在层序遍历时用一个vector<pair<double, int>>容器来记录每一层的元素之和和元素数量。
递归
class Solution {
public:
void averLev(TreeNode* cur, vector<pair<double, int>> &dat, int depth) {
if (!cur) return;
if (dat.size() == depth) dat.push_back(pair<int, int> {cur->val, 1});
else {
dat[depth].first += (double)cur->val;
dat[depth].second++;
}
averLev(cur->left, dat, depth + 1);
averLev(cur->right, dat, depth + 1);
}
vector<double> averageOfLevels(TreeNode* root) {
vector<pair<double, int>> dat;
vector<double> result;
averLev(root, dat, 0);
for (auto iter : dat) {
result.push_back(iter.first / iter.second);
}
return result;
}
};
429.N叉树的层序遍历
https://leetcode.cn/problems/n-ary-tree-level-order-traversal/
和普通的层序遍历差不多,将原本的两步left和right改为for循环
递归
class Solution {
public:
void oderN(Node* cur, vector<vector<int>> &result, int depth){
if(!cur) return;
if(result.size() == depth) result.push_back(vector<int>{});
result[depth].push_back(cur->val);
for(int i = 0; i < cur->children.size(); i++){
oderN(cur->children[i], result, depth + 1);
}
}
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> result;
oderN(root, result, 0);
return result;
}
};
515.在每个树行中找最大值
https://leetcode.cn/problems/find-largest-value-in-each-tree-row/
层序遍历时给每一层记录一个最大值,然后用每一个遍历的元素去比较该层的最大值即可。
迭代
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
vector<int> result;
queue<TreeNode*> que;
if (root) que.push(root);
while (!que.empty()) {
int len = que.size();
int tmp = que.front()->val;
while (len--) {
tmp = tmp >= que.front()->val ? tmp : que.front()->val;
if(que.front()->left)que.push(que.front()->left);
if(que.front()->right)que.push(que.front()->right);
que.pop();
}
result.push_back(tmp);
}
return result;
}
};
116.填充每个节点的下一个右侧节点指针
https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/
本题和下一题使用的相同的代码
117.填充每个节点的下一个右侧节点指针II
https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/
正常层序遍历即可,将每一层元素的next接入该层下一个元素,如果没有就介入nullptr
递归
class Solution {
public:
void con(Node* cur, vector<Node*> &last, int depth){
if(!cur) return;
if(last.size() == depth){
last.push_back(cur);
cur->next = nullptr;
}
else{
last[depth]->next = cur;
last[depth] = cur;
cur->next = nullptr;
}
con(cur->left, last, depth + 1);
con(cur->right, last, depth + 1);
}
Node* connect(Node* root) {
vector<Node*> last;
con(root, last, 0);
return root;
}
};
迭代
class Solution {
public:
Node* connect(Node* root) {
Node* cur;
queue<Node*> que;
if(root) que.push(root);
while(!que.empty()){
int len = que.size();
while(len--){
cur = que.front();
que.pop();
if(len) cur->next = que.front();
else cur->next = nullptr;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return root;
}
};
104.二叉树的最大深度
https://leetcode.cn/problems/maximum-depth-of-binary-tree/
一路层序遍历到尾,记录最后一个元素的深度即可。
递归(最后result++的原因是设置的根节点深度是从0开始,而最终结果要求是从1开始)
class Solution {
public:
void maxD(TreeNode * cur, int & max, int depth){
if(!cur) return;
max = max > depth ? max : depth;
if(cur->left) maxD(cur->left, max, depth + 1);
if(cur->right) maxD(cur->right, max, depth + 1);
}
int maxDepth(TreeNode* root) {
if(!root) return 0;
int result = 0;
maxD(root, result, 0);
result++;
return result;
}
};
迭代
class Solution {
public:
int maxDepth(TreeNode* root) {
int result = 0;
queue<TreeNode*> que;
if(root) que.push(root);
while(!que.empty()){
result++;
int len = que.size();
while(len--){
if(que.front()->left) que.push(que.front()->left);
if(que.front()->right) que.push(que.front()->right);
que.pop();
}
}
return result;
}
};
111.二叉树的最小深度
https://leetcode.cn/problems/minimum-depth-of-binary-tree/
递归(在每一次遍历的时候寻找有没有left和right均为nullptr的节点,记录其深度,和当前记录的最小深度进行比较,最终得到一个最小深度。)
class Solution {
public:
void minD(TreeNode* cur, int &min, int depth){
if(!cur) return;
if(!cur->left && !cur->right){
if(!min) min = depth;
else min = min < depth ? min : depth;
}
if(cur->left) minD(cur->left, min, depth + 1);
if(cur->right) minD(cur->right, min, depth + 1);
}
int minDepth(TreeNode* root) {
if(!root) return 0;
int result = 0;
minD(root, result, 0);
result++;
return result;
}
};
迭代(因为队列的特性,只要找到第一个左节点和右节点均为nullptr的节点就可以返回了)
class Solution {
public:
int minDepth(TreeNode* root) {
int result = 0;
queue<TreeNode*> que;
if(root) que.push(root);
while(!que.empty()){
int len = que.size();
result++;
while(len--){
if(!que.front()->left && !que.front()->right){
return result;
}
if(que.front()->left) que.push(que.front()->left);
if(que.front()->right) que.push(que.front()->right);
que.pop();
}
}
return result;
}
};
226.翻转二叉树
https://leetcode.cn/problems/invert-binary-tree/
可以使用前序和后序,不能用中序,否则会有一部分节点翻转两次,一部分节点不翻转
递归
class Solution {
public:
void invert(TreeNode* cur){
if(!cur) return;
TreeNode* tmp = cur->left;
cur->left = cur->right;
cur->right = tmp;
invert(cur->left);
invert(cur->right);
}
TreeNode* invertTree(TreeNode* root) {
invert(root);
return root;
}
};
迭代(这里cur既用于存储从栈中弹出的节点用用于做交换用的临时节点,可能不直观)
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
stack<TreeNode*> stk;
if(root) stk.push(root);
while(!stk.empty()){
TreeNode* cur = stk.top()->left;
stk.top()->left = stk.top()->right;
stk.top()->right = cur;
cur = stk.top();
stk.pop();
if(cur->left) stk.push(cur->left);
if(cur->right) stk.push(cur->right);
}
return root;
}
};
101. 对称二叉树
https://leetcode.cn/problems/symmetric-tree/
分别以root的left和right节点作为根节点遍历二叉树,遍历方式不限,只要遍历左右顺序相反(比如一个左一个右),只要出现有不同的情况就可以返回false了
递归
class Solution {
public:
bool myCmp(TreeNode* left, TreeNode* right){
if(!left && !right) return true;
if(!(left && right)) return false;
if(left->val != right->val) return false;
return (myCmp(left->left, right->right) && myCmp(left->right, right->left));
}
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return myCmp(root->left, root->right);
}
};
迭代
用一个队列
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(!root) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty()){
TreeNode* ptr1 = que.front();
que.pop();
TreeNode* ptr2 = que.front();
que.pop();
if(!ptr1 && !ptr2) continue;
if(!(ptr1 && ptr2)) return false;
if(ptr1->val != ptr2->val) return false;
que.push(ptr1->right);
que.push(ptr2->left);
que.push(ptr1->left);
que.push(ptr2->right);
}
return true;
}
};
用两个栈(其实一个栈也可以)
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(!root) return true;
stack<TreeNode*> stk1, stk2;
stk1.push(root->left);
stk2.push(root->right);
while(!stk1.empty() && !stk2.empty()){
TreeNode* ptr1 = stk1.top();
TreeNode* ptr2 = stk2.top();
stk1.pop();
stk2.pop();
if(!ptr1 && !ptr2) continue;
if(!(ptr1 && ptr2)) return false;
if(ptr1->val != ptr2->val) return false;
stk1.push(ptr1->right);
stk1.push(ptr1->left);
stk2.push(ptr2->left);
stk2.push(ptr2->right);
}
return true;
}
};