vlambda博客
学习文章列表

507,BFS和DFS解二叉树的层序遍历 II

Standing for right when it is unpopular is a true test of moral character. 

站在不受欢迎但却正确的一边,才是真正的道德考验。

问题描述



给定一个二叉树,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)


例如:

给定二叉树 [3,9,20,null,null,15,7],

 3 / \ 9 20 / \ 15 7

返回其自底向上的层序遍历为:

[ [15,7], [9,20], [3]]


BFS解决



这题类似于二叉树的BFS打印,就是一层一层的打印,一般情况下对于二叉树我们都是从上往下打印,但这题是从下往上打印。直接从下往上不太好操作,可以换种思路,因为题目要求的结果是从下往上就可以了,并没有要求打印的过程。

我们依然可以从上往下打印,只不过打印每一层的时候,结果都要插到列表的最前面,这样最终结果和从下往上打印的结果就完全一样了。

 1public List<List<Integer>> levelOrderBottom(TreeNode root) {
2    //边界条件判断
3    if (root == null)
4        return new ArrayList<>();
5    //队列
6    Queue<TreeNode> queue = new LinkedList<>();
7    List<List<Integer>> res = new ArrayList<>();
8    //根节点入队
9    queue.add(root);
10    //如果队列不为空就继续循环
11    while (!queue.isEmpty()) {
12        //BFS打印,levelCount表示的是每层的结点数
13        int levelCount = queue.size();
14        //subList存储的是每层的结点值
15        List<Integer> subList = new ArrayList<>();
16        for (int i = 0; i < levelCount; i++) {
17            //出队
18            TreeNode node = queue.poll();
19            subList.add(node.val);
20            //左右子节点如果不为空就加入到队列中
21            if (node.left != null)
22                queue.add(node.left);
23            if (node.right != null)
24                queue.add(node.right);
25        }
26        //把每层的结点值存储在res中,插入到最前面
27        //(类似于从下往上打印,关键点在这)
28        res.add(0, subList);
29    }
30    return res;
31}


DFS解决



在前面讲的时候提到过二叉树的BFS和DFS,其中DFS是一直往下走的,到叶子节点然后再返回。对于这道题我们从根节点往下走的时候,每一层都会有一个集合list,用来存放当前层的节点值,如果当前层的list没有创建,就先创建。原理也比较简单,来看下代码

 1public List<List<Integer>> levelOrderBottom(TreeNode root) {
2    List<List<Integer>> res = new ArrayList<>();
3    helper(res, root, 0);
4    return res;
5}
6
7public void helper(List<List<Integer>> list, TreeNode root, int level) {
8    //边界条件判断
9    if (root == null)
10        return;
11    //如果level等于list的长度,说明到下一层了,
12    //并且下一层的ArrayList还没有初始化,我们要
13    //先初始化一个ArrayList,然后放进去。
14    if (level == list.size()) {
15        list.add(0new ArrayList<>());
16    }
17    //这里就相当于从后往前打印了
18    list.get(list.size() - level - 1).add(root.val);
19    //当前节点访问完之后,再使用递归的方式分别访问当前节点的左右子节点
20    helper(list, root.left, level + 1);
21    helper(list, root.right, level + 1);
22}


总结



只要明白二叉树的BFS遍历,这题就很容易解决,虽然这题结果是从下往上,但我们只需要在每层节点值存储的时候修改一下位置即可。




如果觉得有用就点个"赞"吧