题目描述
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
- 示例:
输入:给定二叉树 [3, 9, 20, null, null, 15, 7]
输出:[[15,7], [9,20], [3]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
因为是层次遍历,所以直接选择BFS。
但需按从底部到根部的返回顺序,方法一是使用Collections.reverse(),方法二是使用栈后入先出的特点进行逆顺序返回。因整体思路一致,以下代码以第二种方法为例进行详解。
代码详解
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> list = new LinkedList<>(); // list为最终返回的列表
if (root == null) { // 单独拎出空树这一特殊情况
return list;
}
Queue<TreeNode> queue = new LinkedList<>(); // BFS最爱的队列,老顾客了
Stack<List<Integer>> stack = new Stack<>(); // 栈,后入先出,用于反转
List<Integer> temp = new LinkedList<>(); // 临时列表,用于存放根节点的数值
temp.add(root.val);
stack.push(temp); // 把根节点的数值放入栈中
temp = null;
// 以下便是经典的BFS
queue.offer(root.left);
queue.offer(root.right);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> l = new LinkedList<>(); // 存放每一层所有节点的值
while (size > 0) {
TreeNode p = queue.poll();
TreeNode q = queue.poll();
if (p != null) {
l.add(p.val);
queue.offer(p.left);
queue.offer(p.right);
}
if (q != null) {
l.add(q.val);
queue.offer(q.left);
queue.offer(q.right);
}
size = size - 2; // 因为每次取出两个节点,因此-2
}
stack.push(l); // 把当前层的列表入栈
}
stack.pop(); // 这里是值得优化的地方,
// 因为在上面while循环的倒数第二次循环中,把所有叶子节点的子节点(全是null)也放入队列中了
// 因此最后一遍循环把一个空的列表放入了栈中
// 所以在循环结束后,把最后这一空的列表先弹出,然后再执行下面的代码
while (!stack.isEmpty()) {
list.add(stack.pop());
}
return list;
}
}
注意点
- 一层一层地遍历首先想到BFS。
- 如果第104题使用的BFS,那么此题也会迎刃而解。(本人只用了迭代,Orz)
- 可以额外加入限定条件,使得外层while的最后一次循环不用把一个空列表放入栈中。