leetcode
leetcode 1351 ~ 1400
寻找所有的独生节点

寻找所有的独生节点

难度:

标签:

题目描述

代码结果

运行时间: 36 ms, 内存: 16.4 MB


// 题目思路:
// 使用Java Stream和递归结合实现,依然遍历二叉树,找到所有独生节点。
// 独生节点的定义和Java版本相同。需要注意的是,在使用Stream时,不推荐直接操作null,因此可以用Optional包装。

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Solution {
    // 定义树节点类
    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }

    public List<Integer> findLonelyNodes(TreeNode root) {
        return findLonelyNodesHelper(root).collect(Collectors.toList());
    }

    private Stream<Integer> findLonelyNodesHelper(TreeNode node) {
        if (node == null) {
            return Stream.empty(); // 如果当前节点为空,返回空Stream
        }
        Stream<Integer> lonelyNodes = Stream.empty();
        if (node.left != null && node.right == null) {
            lonelyNodes = Stream.of(node.left.val); // 左子节点为独生节点
        } else if (node.right != null && node.left == null) {
            lonelyNodes = Stream.of(node.right.val); // 右子节点为独生节点
        }
        // 使用Stream.concat合并当前节点的结果和子节点的结果
        return Stream.concat(lonelyNodes, Stream.concat(findLonelyNodesHelper(node.left), findLonelyNodesHelper(node.right)));
    }
}

解释

方法:

该题解采用了迭代方式进行二叉树的遍历,主要使用了栈(stack)来模拟递归过程,从而对二叉树进行深度优先搜索(DFS)。在遍历时,每当访问一个节点,检查其是否具有独生子节点(即只有左孩子或只有右孩子),若是,则将该子节点的值加入结果列表。通过先进后出的栈结构,先将当前节点推入栈中,然后移动到左子节点,直到左侧无子节点,再从栈中取出节点转向右子节点。这种方式确保了每个节点都被访问一次。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在迭代方式的二叉树深度优先搜索中,为什么选择使用栈(stack)而不是队列(queue)来模拟这个过程?
在二叉树的深度优先搜索(DFS)中,使用栈是为了模拟递归的行为,即后进先出的特性。递归的执行本质上是在调用栈上操作,每次处理最后进入的元素。如果使用队列(先进先出的特性),则会变成宽度优先搜索(BFS),这种搜索方式会按层级遍历树,而不是深入到每个分支的末端,这与深度优先搜索的目标不符。
🦆
在该算法中,如果一个节点既有左子节点又有右子节点,它们是否会被考虑为独生节点?如果不是,为什么?
如果一个节点既有左子节点又有右子节点,这两个子节点都不会被考虑为独生节点。根据题目的定义,独生节点是指一个节点只有一个子节点(要么只有左子节点,要么只有右子节点)。因此,如果一个节点的两个子节点都存在,这两个子节点均不满足独生节点的条件。
🦆
在从栈中弹出节点并转向右子节点的过程中,是否需要再次检查右子节点是否独生,并处理相应逻辑?
在从栈中弹出节点并转向右子节点的过程中,不需要再次检查右子节点是否独生。这是因为右子节点的独立性已经在其父节点被第一次访问时判断过了。在算法中,每个节点在第一次遇到时(未从栈中弹出前)就已经完成了对其子节点的独生状态检查。因此,不必在转向右子节点时重复这一检查。
🦆
该题解中如何处理树中的节点值为null的情况,尤其是在检查子节点是否存在时?
在该题解中,树中节点值为null的情况通常指的是某个节点不存在左子节点或右子节点。这在代码中通过检查 `root.left` 和 `root.right` 是否为 `None` 来处理。如果 `root.left` 为 `None`,则说明没有左子节点;如果 `root.right` 为 `None`,则说明没有右子节点。这种处理方式确保了在添加独生节点值至结果列表时,不会因为尝试访问不存在的子节点的值而导致错误。

相关问题