102. 二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 示例: 二叉树:
[3,9,20,null,null,15,7],
3/ \9 20/ \15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
解题思路
本题和第二周的 429. N叉树的层序遍历 其实几乎是同一个题,二叉树的层次遍历只是N叉树层序遍历的一种特殊情况。除了需要层次遍历以外,本题还要求打印出每层所包含的结点。普通的层序遍历每次从队列中取出一个结点,并将其踢出队列,然后将该结点的所有子结点push到队列中。
如果简单模拟下这个过程:
3
/ \
9 20
/ \ / \
6 8 15 7
一开始将root结点3入队 | 3所在层数为1,操作完后队列中元素个数为1个 [ 3 ]
取出队首元素3,将其子结点9和20入队 | 9和20所在层数为2,操作完后队列中元素个数为2个 [ 9 20]
取出队首元素9,将其子结点 6和 8 入队 | 6和8所在层数为3,操作完后队列中元素个数为3个 [ 20 6 8 ]
取出队首元素20,将其子结点 15和 7 入队 | 15和7所在层数为3,操作完后队列中元素个数为4个 [ 6 8 15 7 ]
………………..
当遍历9和20时,9和20是同一层的结点,其实是要分别取出它们,并把它们的孩子结点push到队列中的,而它们的孩子结点其实是同一层的,所以我们可以在不断从队列中[取结点push子结点]这个操作之前控制这部分结点是同层结点。怎么知道哪些是同层结点呢,在上面的例子中,在操作完[取队首3,push孩子9和20]后,队列的个数变为2个,而它们两个就是同层结点,我们记录此时队列的大小,即是这层的结点个数,循环遍历每个结点把它们的孩子push到队列中,而两个结点都操作完之后此时队列结点个数为4,是第三层。记录此时队列数,重复上面的操作………..
每层我们所记录的队列中结点个数(同层个数),其实就是来源于上一层所有结点作完操作之后队列里面的结点个数,具体看如下核心代码
while(!que.empty()){
vector<int> layer;//记录同层结点
/*que.size()来自上一层结点把所有子结点入队后的结点个数 */
for(int i=que.size();0<i;i--){
TreeNode* top = que.front();
que.pop();//去掉当层此结点
if(top->left != NULL)
que.push(top->left);//入下层左孩子
if(top->right != NULL)
que.push(top->right);//下层右孩子
layer.push_back(top->val);
}
res.push_back(layer);
}
完整代码实现
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> que;
if(root != NULL)
que.push(root);
while(!que.empty()){
vector<int> layer;
/*此处不可以为 for(int i=0;i<que.size();i++)
因为这样que.size()会随着上次循环的push操作而动态变化*/
for(int i=que.size();0<i;i--){
TreeNode* top = que.front();
que.pop();
if(top->left != NULL)
que.push(top->left);
if(top->right != NULL)
que.push(top->right);
layer.push_back(top->val);
}
res.push_back(layer);
}
return res;
}
};
