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}
,
/ \ / \
return its level order traversal as:
[
[],
[,],
[,]
]
题解:二叉树的层次遍历,用队列实现。重点在于如何判断每一层的结束和下一层的开始。
用一个变量nextLevelStarter记录下一层的开始节点,最初为root的左子或者右子(如果左子为空),每一层遍历开始的时候赋值为null。在遍历这一层时,观察当前遍历节点的左子和右子,如果nextLevelStarter当前为空,且当前节点的左子不为空,那么说明当前节点的左子是下一层的第一个节点,就把当前节点的左子赋值给nextLevelStarter;如果左子为空,再看右子。如果当前节点的左右子都为空,那么nextLevelStarter应该是当前节点这一层后面的节点的孩子,就继续遍历当前这一层。以上面的例子说明,遍历第二层时从9开始,发现9的左子和右子都为空,那么nextLevelStarter就保持为null,遍历到20的时候,发现20的左子不为空,那么就把nextLevelStarter赋值为20的左子,即下一层的第一个节点。这时候nextLevelStarter已经不为空了,那么即使20后面还有节点,也不会改变nextLevelStarter的值了。
代码如下:
public class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> answerList = new ArrayList<List<Integer>>();
TreeNode nextLevelStarter;
Queue<TreeNode> q = new LinkedList<TreeNode>(); q.add(root);
if(root != null){
if(root.left != null)
nextLevelStarter = root.left;
else if(root.right != null)
nextLevelStarter = root.right;
else {
List<Integer> temp = new ArrayList<Integer>();
temp.add(root.val);
answerList.add(temp);
return answerList;
}
}
else
return answerList; while(!q.isEmpty()){ TreeNode currentNode = q.peek();
List<Integer> thisLevelList = new ArrayList<Integer>();
//每层遍历开始的时候把nextLevelStarter赋值为null,遍历这一层的时候顺便找下一层的开始节点
nextLevelStarter = null; //没有到达下一层的开始节点时继续遍历
while(q.peek() != nextLevelStarter && q.isEmpty() == false){
currentNode = q.remove(); //如果nextLevelStarter值为空,说明还没找到下一层的起始节点
//那么就查看当前遍历的节点的孩子是否为空,不为空就是下一层的起始节点
if(nextLevelStarter == null){
if(currentNode.left != null)
nextLevelStarter = currentNode.left;
else {
if(currentNode.right != null){
nextLevelStarter = currentNode.right;
}
}
} thisLevelList.add(currentNode.val);
if(currentNode.left != null)
q.add(currentNode.left);
if(currentNode.right != null)
q.add(currentNode.right);
} answerList.add(thisLevelList);
}
return answerList;
}
}
还要积累一下java中队列的使用方法:
1.声明和初始化:
Queue<TreeNode> q = new LinkedList<TreeNode>();
2.add()函数:往队列中加入一个值
3.peek()函数:返回队列头但不删除队列头
4.remove()函数:返回队列头并且删除队列头
java中声明二维列表的方法:
List<List<Integer>> answerList = new ArrayList<List<Integer>>();
做这道题的时候还遇到一个问题,就是开始时候想在每一层结束后把存放当前层节点信息的列表thisLevelList加入到answerList这个二维列表后就把thisLevelList清空,就不用在每层开始遍历的时候都要声明thisLevelList了,后来发现这种方法不可行,因为把thisLevelList清空后answerList里面加入的thisLevelList的值也没有了,想了一下原因应该是每次声明thisLevelList的时候都开辟了一块内存,当把thisLevelList加入answerList的时候,answerList直接设置一个指针指向这块内存,所以如果把这块内存清空,answerList里面指向的值就对应请空了。所以在遍历每一层的时候都要申请新的内存空间存放当前这一层节点的值。
说好半个小时写完的,高估自己了,碎觉~