描述:
Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its level order traversal as:
[
[3],
[9,20],
[15,7]
]
将一棵树按照水平遍历的顺序,从左到右返回每一层的所有节点的值,一层一层地返回,一个多维数组。
思路:
每一次要扫遍每一层的节点并且将这些节点的整数值添加到一个数组中,那么我们必须要有一个二维数组,还有一个一维数组来每次保存节点数值,并且添加到二维数组中,直到最后一层的所有节点全部扫完。
要一层层扫描完所有的节点,就很容易联想到bfs了,先上后下,先左后右。
1.BFS
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int> > value; //返回的多维数组
if(root == NULL){return value;}
queue<TreeNode* > q;
q.push(root);
while(!q.empty()){
vector<int> level; //每一次要压入的数组
int i = 0;
int size = q.size();
for(i = 0; i < size;i++){ //这个指定了每次只能执行的push_back操作次数,由每次q压进队列的元素数量决定
TreeNode* temp = q.front();
q.pop();
level.push_back(temp->val);
if(temp->left != NULL){
q.push(temp->left);
}
if(temp->right != NULL){
q.push(temp->right);
}
}
value.push_back(level);
}
return value;
}
};
每次记录下队列的下一个队列的长度,每次轮询完一层,上个循环push了几次进来,当前就pop了几次,每次都是新的一层。如果没有想明白,可以自己画图方便理解。
注意每一次for循环结束的时候,刚刚好将下一层需要循环的所有节点全部都push进队列中了,同时pop了所有当前层的所有节点,如果是满二叉树,那就是1 –> 2 –> 4 –> 8 ……
python:
class Solution(object):
def levelOrder(self, root):
value = []
if root == None:
return value
q = [root]
while q:
level = []
new_q = []
for i in q:
level.append(i.val)
value.append(level)
for item in q:
if item.left != None:
new_q.append(item.left)
if item.right != None:
new_q.append(item.right)
q = new_q
return value
以上的代码可简化为:
class Solution(object):
def levelOrder(self, root):
value = []
if root == None:
return value
q = [root]
while q:
new_q = []
value.append([i.val for i in q]) #直接将q中的每一个元素作为list传回去,减少了一些步骤,应该熟悉这种写法
for item in q:
if item.left != None:
new_q.append(item.left)
if item.right != None:
new_q.append(item.right)
q = new_q
return value
2.使用多个队列来控制一层一层地遍历
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int> > value; //返回的多维数组
if(root == NULL){return value;}
queue<queue<TreeNode*> > q; //包含每一层队列的总队列
queue<TreeNode*> temp1; //临时队列,只为了构造q
temp1.push(root);
q.push(temp1);
while(!q.empty()){
vector<int> level; //每一次要压入的数组
queue<TreeNode* > q2 = q.front();
queue<TreeNode* > q3;
while(!q2.empty()){
TreeNode* temp = q2.front();
level.push_back(temp->val);
q2.pop();
if(temp->left){
q3.push(temp->left);
}
if(temp->right){
q3.push(temp->right);
}
}
q.pop();
value.push_back(level);
if(!q3.empty()){
q.push(q3);
}
}
return value;
}
};
大致过程:
我们这里使用了一个q — 保存子队列的队列,q2是每次取得q中的第一个队列,也就是保存了某一层节点的队列,在扫描q2的节点的时候,我们会对q2中的每个节点进行是否有子节点判断,并压入q3队列,将q3压入q中到得到下一次需要循环的队列。
能看出来,每一次的q只有一个元素front,就是当前层的全部节点队列。