二叉树层次遍历(递归版)

题目:

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

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

    3
   /
  9  20
    / 
   15   7

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析:

看到这个题目我第一反应是递归,不过貌似好像大概还有挺多不同的解法。本篇文章记录一下我的递归思路,其他的算法留待日后学习。

力扣上给出的空方法模板的返回值为List<List<Integer>>,结合题干可知,每一层的节点数值应按顺序存入一个集合中,所有的节点集合也要保存在一个集合中。

那么问题来了,对于方法而言,二叉树的层数是未知的,那么应该创建多少个节点集合呢?可以先用递归来求一下二叉树的最长路径,但是,考虑到时间复杂度和空间复杂度的话,我否定了这个想法。

最终我选择在递归中创建节点集合,当访问到每一层的最左节点时,创建该层的节点集合,方法就是通过一个int值来记录二叉树的层数,当到达二叉树的第一层(顶层)时,int为0,此时集合内尚未创建顶层节点集合,事实上这个时候集合内没有任何节点集合,所以它的size为0,以此类推,我们分析可知,当集合的size小于等于当前层数记录(也就是int值)的时候,需要创建当前层的节点集合。

当递归访问下一层时,需将当前层数记录+1传给递归方法。

最终由于集合最先添加的是顶层节点的集合,最后添加的是最底层叶子节点的集合,所以按照题目要求,最终需要将集合倒序排列。

题解:

/**
 * 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>> lists = new ArrayList<>();
        getVal(root, lists, 0);
        Collections.reverse(lists);
        return lists;
    }

    public void getVal(TreeNode root, List<List<Integer>> lists, int curr) {
        if (root == null) {
            return;
        }
        if (lists.size() <= curr) {
            lists.add(new ArrayList<>());
        }
        lists.get(curr).add(root.val);
        getVal(root.left, lists, curr + 1);
        getVal(root.right, lists, curr + 1);
    }
}

本篇小结:

其实,这些二叉树、递归什么的概念之前一直是知道的,但也仅限于知道而已,可以说没有真正的好好练习和应用过,最近学习算法的时候有几次用到,没想到还挺香~

不过在做这道算法题的时候,还是小小的纠结了一下,我当时的疑惑是递归方法会按照我预想的顺序执行吗?

假设现在有一个二层的二叉树:

    6
   /
  7  8

我希望的执行顺序是先将6添加进集合,再将7添加进集合,最后将8添加进集合。

在递归方法中首先将6添加进集合,然后依次调用了访问节点7和节点8的递归,虽然代码是有先后次序,但是方法执行时会按照次序执行吗?

在实践中发现,是我想多了,顿时觉得心情舒畅,看来以后可以更加愉快的使用递归了!

第二个收获就是又发现了一个宝藏方法Collections.reverse(),将集合倒序重排,爱了爱了。

原文地址:https://www.cnblogs.com/wxdmw/p/13277719.html