题目:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其自底向上的层次遍历为:
[
[15,7],
[9,20],
[3]
]
方法1. 常规层次遍历,额外变量存储每层节点数
public List<List<Integer>> levelOrderBottom(TreeNode root) {// 正向遍历,最后反转ans
List<List<Integer>> ans = new LinkedList<>();
if (root == null) return ans;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int curLevelCount = 1, nextLevelCount = 1;
while (!que.isEmpty()) {
List<Integer> curLevelNode = new ArrayList<>(); //存每层节点数
curLevelCount = nextLevelCount;
nextLevelCount = 0;
while (!que.isEmpty() && curLevelCount-- > 0) {
TreeNode cur = que.poll();
curLevelNode.add(cur.val);
if (cur.left != null) {
nextLevelCount++;
que.offer(cur.left);
}
if (cur.right != null) {
nextLevelCount++;
que.offer(cur.right);
}
}
ans.add(curLevelNode);
}
Collections.reverse(ans); // 反转层次遍历的列表
return ans;
}
方法2. 优化版本
别一直用List声明ans了,可以个性化,用LinkedList 就能用addFirst() 这种方法了。
直接把每层节点加入ans头插,就不用在最后反转了。
另外,每次遍历这一层之前,队列当前的元素个数就是这一层节点个数,不用额外变量存。
注意,for循环i的上限界不能用que.size() 因为在遍历这一层的时候,下一层节点也会动态加入。
public List<List<Integer>> levelOrderBottom(TreeNode root) {
// 直接用LinkedList定义,不用List,这样就能直接ans.addFirst()了
LinkedList<List<Integer>> ans = new LinkedList<>();
if (root == null) return ans;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
List<Integer> curLevelNode = new ArrayList<>();
int curLevelCount = que.size(); // 队列当前元素数就是当前层节点数
for (int i = 0; i < curLevelCount; ++i) {
TreeNode cur = que.poll();
curLevelNode.add(cur.val);
if (cur.left != null)
que.offer(cur.left);
if (cur.right != null)
que.offer(cur.right);
}
ans.addFirst(curLevelNode);
}
return ans;
}