二叉树层次遍历(递归版)
题目:
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [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(),将集合倒序重排,爱了爱了。