Question
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,#,#,15,7},
3
/ \
9 20
/ \
15 7
return its level order traversal as:
[
[3],
[9,20],
[15,7]
]
OJ’s Binary Tree Serialization:
The serialization of a binary tree follows a level order traversal, where ‘#’ signifies a path terminator where no node exists below.
Here’s an example:
1
/ \
2 3
/
4
\
5
The above binary tree is serialized as “{1,2,3,#,#,4,#,#,5}”.
Java Code
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public List<List<Integer>> levelOrder(TreeNode root) {
LinkedList<List<Integer>> nodes = new LinkedList<List<Integer>>();//存储所有层节点的val
LinkedList<TreeNode> list = new LinkedList<>();//节点队列,存储当前遍历的层的所有节点
//若输入为空树,则返回空的nodes
if(root == null) return nodes;
//将根节点root和层标志位null入队
list.add(root);
list.add(null);
//将根节点的val保存到nodes的第一个List集合中
List<Integer> levelNodes = new LinkedList<Integer>();
levelNodes.add(root.val);
nodes.add(levelNodes);
TreeNode temp, Left, Right;
//如果队列中不是仅剩标志位一个元素
while(list.size() != 1) {
//遍历二叉树新的一层,先new一个List并添加到nodes中,用于保存当前层的节点值
levelNodes = new LinkedList<Integer>();
nodes.add(levelNodes);
//通过出队依次访问当前层所有节点得到对应的子节点,直到遇到层标志位null
while ((temp = list.poll()) != null) {
if((Left = temp.left) != null) {
list.add(Left);//当前节点的左子节点入队
levelNodes.add(Left.val);//保存节点的val
}
if((Right = temp.right) != null) {
list.add(Right);//当前节点的右子节点入队
levelNodes.add(Right.val);
}
}
//已遍历完一层,在队尾设置新的层标志位
list.add(null);
}
//最后一次层次遍历没有节点
nodes.removeLast();
return nodes;
}
说明
- 二叉树的层次遍历使用广度优先搜索算法(BFS,breadth-first search),一般通过队列或链表实现。从根节点开始,每一层的节点依次入队,层与层之间设置隔离标志位(null),然后按照先进先出的规则,每一层依次出队,每个节点出队的同时,获取其左右子节点,并依次入队,同时保存节点的val,从而能够取出二叉树中每一层的节点。
更新
2016.05.03
下面以问题中给的二叉树为例,简述代码的执行逻辑:
内层while循环开始之前,各个变量为list [null, node3] levelNodes [3] nodes [3]
进入第一次while循环,先给nodes添加一个空的List,即levelNodes
levelNodes [3] nodes [[3], []]
然后list的第一个元素(节点node3)出队,得到其左右两个子节点,并依次从list的尾部入队,同时保存这两个子节点的val到nodes的空List中,得到
list [node20, node9, null] levelNodes [9, 20] nodes [[3], [9, 20]]
然后list的第二个元素(null)出队,它就是第一层节点结束的标志位,则第一层所有节点已经遍历完,内层while循环结束,此时list中存放的就是第二层的所有节点了,我们在其尾部将null入队,作为第二层的结束标志位。则第二次while循环开始之前,各个变量为
list [null, node20, node9] levelNodes [] nodes [[3], [9, 20]]
然后重复上述步骤,依次将list中的元素出列,得到第三层的节点并将它们入列。当内层while完成第三次循环后,list只剩下层标志位null了,此时外层的while循环判断为假,结束所有循环,注意最后一次我们往nodes中添加了一个空list,所以return之前要删除它。