leetcode
leetcode 301 ~ 350
寻找二叉树的叶子节点

寻找二叉树的叶子节点

难度:

标签:

题目描述

代码结果

运行时间: 27 ms, 内存: 15.9 MB


/*
 * 题目:寻找二叉树的叶子节点
 * 思路:
 * 1. 使用递归的方法遍历二叉树。
 * 2. 在遍历过程中,将叶子节点加入一个列表。
 * 3. 使用Java Stream将叶子节点收集到一个新的列表中。
 */
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
public class FindLeavesStream {
    public List<Integer> findLeaves(TreeNode root) {
        return findLeavesHelper(root).collect(Collectors.toList());
    }
 
    private Stream<Integer> findLeavesHelper(TreeNode node) {
        if (node == null) return Stream.empty();
        if (isLeaf(node)) {
            return Stream.of(node.val);
        } else {
            return Stream.concat(findLeavesHelper(node.left), findLeavesHelper(node.right));
        }
    }
 
    private boolean isLeaf(TreeNode node) {
        return node.left == null && node.right == null;
    }
}

解释

方法:

这个题解的思路是使用递归的方式遍历二叉树,在递归过程中计算每个节点距离叶子节点的高度(最大深度)。将相同高度的节点的值存储在同一个列表中,最终得到按高度分组的叶子节点列表。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在这个算法中,如何确保所有叶子节点都被正确地分类到最底层的列表中?
在这个算法中,所有叶子节点被分类到最底层的列表中是通过递归函数`maxDepth`的返回值来确保的。叶子节点是没有左子树和右子树的节点,所以对于叶子节点,`maxDepth`返回的是1(`max(0, 0) + 1`)。这意味着叶子节点总是被放在`self.res[0]`的位置,即最底层的列表中。因为他们的高度`h`被计算为1,使用`h-1`作为索引时正好指向列表的第一个位置。
🦆
递归函数`maxDepth`返回的是从当前节点到叶节点的最大深度,那么在递归过程中,如何处理只有左子树或只有右子树的情况?
当一个节点只有左子树或只有右子树时,`maxDepth`函数会递归地调用存在的子树并计算其深度,而另一个为`None`的子树的深度会返回0。例如,如果只有左子树,`left_depth`将是该左子树的最大深度,而`right_depth`将是0。然后,当前节点的高度计算为`max(left_depth, right_depth) + 1`,即仅考虑存在的子树的深度加1。这样可以正确地评估出从当前节点到叶节点的最大深度。
🦆
在算法中,列表`self.res`的索引是如何与节点的高度对应起来的?具体地,为什么用`h-1`作为索引?
在这个算法中,`self.res`列表的索引是通过节点的高度`h`来确定的,其中`h`是当前节点到叶节点的最大深度。由于列表索引是从0开始的,而高度是从1开始的,因此使用`h-1`作为索引来对应高度`h`的节点。这样,高度为1的节点(叶子节点)就存储在索引0的位置,高度为2的节点存储在索引1的位置,以此类推。
🦆
为什么在添加新列表到`self.res`时,要检查`len(self.res) < h`?这种情况下,是否可能出现`self.res`长度大于`h`的情况?
在添加新列表到`self.res`时,检查`len(self.res) < h`是为了确保在尝试将节点值添加到`self.res[h-1]`时该索引已经存在。这防止了索引错误。如果当前节点的高度`h`大于`self.res`的当前长度,说明我们还没有为这个高度创建存储节点的列表,因此需要添加新的空列表。在正常运行的递归过程中,`self.res`的长度不可能大于`h`,因为`h`是从根节点向下递增的,而每次遇到新的高度才会添加新的列表。

相关问题