leetcode
leetcode 1501 ~ 1550
二叉树的最近公共祖先 IV

二叉树的最近公共祖先 IV

难度:

标签:

题目描述

代码结果

运行时间: 71 ms, 内存: 20.3 MB


/*
题目思路:
1. 与普通的Java解法相同,但在处理节点集合时使用流(Stream)API。
2. 将节点的值收集到一个Set中,然后递归寻找LCA。
*/

import java.util.Set;
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 Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode[] nodes) {
        Set<Integer> values = Stream.of(nodes).map(node -> node.val).collect(Collectors.toSet());
        return findLCA(root, values);
    }
    
    private TreeNode findLCA(TreeNode root, Set<Integer> values) {
        if (root == null) return null;
        if (values.contains(root.val)) return root;
        TreeNode left = findLCA(root.left, values);
        TreeNode right = findLCA(root.right, values);
        if (left != null && right != null) return root;
        return left != null ? left : right;
    }
}

解释

方法:

这个题解使用了递归的深度优先搜索(DFS)来寻找最近公共祖先。函数`dfs`从二叉树的根节点开始,向下遍历每一个节点。如果当前节点为空,返回`None`。如果当前节点是待查询的节点列表`nodes`中的一个,直接返回该节点。然后递归地在左右子树上调用`dfs`函数,得到左子树和右子树的返回结果`l`和`r`。如果某一侧返回了`None`,说明这一侧没有找到任何`nodes`中的节点,因此返回另一侧的结果。如果两侧都返回了非`None`的结果,说明当前节点是两个子树返回的节点的公共祖先,因此返回当前节点。这个递归过程持续进行,直到遍历完所有节点,或找到最近的公共祖先。

时间复杂度:

O(n)

空间复杂度:

O(h + k)

代码细节讲解

🦆
如何处理`nodes`列表中包含重复节点的情况?是否会影响算法的结果或性能?
在当前算法中,如果`nodes`列表中包含重复的节点,算法仍然可以正确地返回最近公共祖先,但这会导致性能上的一些不必要消耗,因为重复的节点每次被遇到时都会进行处理。为了提高效率,可以在算法开始之前将`nodes`列表转换成一个集合,这样可以快速检查一个节点是否在目标节点集中,并且自动去除重复项。
🦆
在递归函数`dfs`中,你是如何判断一个节点是否属于`nodes`列表的?使用什么数据结构可以优化这一查找过程?
在题解中,判断一个节点是否属于`nodes`列表是通过简单的`in`操作实现的。这种方法在`nodes`为列表时的时间复杂度为O(n),其中n是列表的长度。为了优化这个查找过程,可以使用集合(`set`)数据结构,因为集合的查找时间复杂度平均为O(1)。在算法开始前,将`nodes`列表转换为一个集合可以显著提高效率。
🦆
如果输入的二叉树非常倾斜(例如所有节点都在左侧或右侧),递归深度将会非常深。在这种情况下,如何优化代码以防止栈溢出?
在极端倾斜的二叉树中,递归深度可能会非常高,从而导致栈溢出。为了解决这个问题,可以考虑使用迭代而非递归来实现深度优先搜索(DFS)。具体方法包括使用显式栈来模拟递归过程,或者改用广度优先搜索(BFS),使用队列来实现。这样可以避免深层递归造成的栈溢出问题。
🦆
题解中提到如果两侧都返回了非`None`的结果,则当前节点是公共祖先。这是否意味着算法总是返回最近的公共祖先,还是可能返回较远的公共祖先?
题解中的算法确保总是返回最近的公共祖先。这是因为只有在两个不同子树中各自找到了至少一个目标节点时,当前节点才会被确定为公共祖先并返回。此时,返回的是最低的(即最近的)公共祖先,因为一旦一个节点被确定为公共祖先,递归将停止在更高的祖先节点上进行检查。

相关问题