二叉树的层序遍历
层序遍历就是从上到下、从左到右的遍历二叉树,可以借助队列来实现。
队列先进先出,符合一层一层遍历的逻辑。
题目1:102.二叉树的层序遍历(模板)
解题思路:
从上到下,那么就首先将根节点入队,其实也就是将第一层入队,这里要进行一个判空,如果队列不为空,那么就将队列里的元素放入数组中,然后进行下一层的拓展,直到队列为空。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) { //传入的数据为二叉树头节点指针
queue<TreeNode*> que; //用队列存储节点的指针,实现层序遍历
vector<vector<int>> result; //用一个二元组(node,level)表示状态,将同一层的放在一起
if (root != NULL) que.push(root); //判断是否为空,不为空首先将根节点入队
while (!que.empty()) {
int size = que.size(); //求当前队列的长度s
vector<int> vec; //用vec存储每一层
for (int i = 0; i < size; i++) { //依次从队列中取s个元素入队(即每一层)
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:107.二叉树的层次遍历II
解题思路:
102是从上到下,这一题要求自底向上。其实还是可以套用102的模板,只需要将最后的result反转。
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;
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:199.二叉树的右视图
解法一:广度优先搜索
解题思路:
这题刚开始被示例误导了,以为只要去掉node->right就可以,但是仔细一想,左子树可以比右子树长,只要不被右子树遮挡,在右侧依然能够看到。
但是依然可以套用102的模板,利用广度优先搜索进行层次遍历,每遍历一层就记下该层最后一个元素(下图红色)
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*>que;
vector<int> result; //根据返回值确定放入result的数据类型
if (root != NULL) 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)) result.push_back(node->val); //将每一层的最后元素放入result数组中
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
解法二:深度优先搜索
解题思路:
在深度优先搜索中,并不一定要拘泥于前中后序遍历三种形式,比如这一题,如果按照 根节点->右子树->左子树的顺序遍历二叉树,那么在遍历过程中每层都是最先访问最右边的节点。
class Solution {
public:
vector<int> result;
void DFS(TreeNode* root, int depth) {
if (root == NULL) return;
if (depth == result.size()) {
result.push_back(root->val);
}
depth++;
DFS(root->right, depth);
DFS(root->left, depth);
}
vector<int> rightSideView(TreeNode* root) {
DFS(root, 0);
return result;
}
};
题目4:637.二叉树的层平均值
解法一:广度优先搜索
每一层节点的平均值,那么就可以用BFS进行遍历然后求和求平均值
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();
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);
}
result.push_back(sum / size); //将一层的数据保存
}
return result;
}
};
解法二:深度优先搜索
DFS就比较麻烦了,要用两个数组,一个存储二叉树的每一层节点数,另外一个存储二叉树每一层节点的和,然后在数组中计算每层节点的和。
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<int> counts; //存储二叉树的每一层节点数
vector<double> sums; //存储二叉树每一层节点的和
vector<double> result;
dfs(root, 0, counts, sums); //从第0层的根节点开始
int size = sums.size(); //这句不能写在dfs前面
for (int i = 0; i < size; i++) {
result.push_back(sums[i] / counts[i]);
}
return result;
}
void dfs(TreeNode* root, int i, vector<int>& counts, vector<double>& sums) {
if (root == NULL) return;
if (i < sums.size()) { //访问到的节点在第i层
sums[i] += root->val;
counts[i] += 1;
}
else { //访问到的节点在别的层,就在数组中尾部添加一个节点值和节点个数
sums.push_back(root->val);
counts.push_back(1);
}
dfs(root->left, i + 1, counts, sums);
dfs(root->right, i + 1, counts, sums);
}
};
题目5:429.N叉树的层序遍历
解题思路:
从二叉树变成了N叉树,那么只需要修改二叉树向左右子树遍历的方式即可
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(); //N叉树当前层节点个数
vector<int> vec;
for (int i = 0; i < size; i++) {
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;
}
};
题目6:515.在每个树行中找最大值
层序遍历,将每一行的最大值添加进数组
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 maxvalue = INT_MIN;
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
maxvalue = node->val > maxvalue ? node->val : maxvalue;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(maxvalue);
}
return result;
}
};