二叉树的最近公共祖先 II
难度:
标签:
题目描述
代码结果
运行时间: 124 ms, 内存: 20.3 MB
/*
* Leetcode 1644: Lowest Common Ancestor of a Binary Tree II using Java Streams
*
* 思路:
* 使用流的方式不适合解决树的递归问题,因为流更适合处理集合,而树的结构要求递归处理。此处依然使用递归方法,只是展示如何在树的遍历过程中使用流处理集合。
*/
public class Solution {
private boolean foundP = false;
private boolean foundQ = false;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
TreeNode lca = findLCA(root, p, q);
if (foundP && foundQ) {
return lca;
}
return null;
}
private TreeNode findLCA(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
TreeNode left = findLCA(root.left, p, q);
TreeNode right = findLCA(root.right, p, q);
if (root == p) {
foundP = true;
return root;
}
if (root == q) {
foundQ = true;
return root;
}
if (left != null && right != null) {
return root;
}
return left != null ? left : right;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
解释
方法:
这个解法使用了递归的方式来查找二叉树的最近公共祖先。递归函数 `helper` 从根节点开始,对二叉树进行后序遍历(即先探索子节点,再处理当前节点)。在探索过程中,当到达叶节点或已找到最近公共祖先时,递归会回溯。在每个节点,函数检查其左右子节点是否包含节点 p 或 q。如果当前节点自身是 p 或 q,或其任一子树包含 p 或 q,该节点会向其父节点报告这一发现。如果一个节点的两个子树各包含一个目标节点(p 或 q),那么该节点就是最近的公共祖先。为保存这个结果,使用了一个非局部变量 `res`。当找到最近公共祖先后,无需进一步递归,因此可以提前结束递归过程。
时间复杂度:
O(n)
空间复杂度:
O(h)
代码细节讲解
🦆
在递归函数`helper`中,返回值是如何帮助确定最近公共祖先的?具体的返回逻辑是怎样的?
▷🦆
函数中使用了`nonlocal res`关键字,能否详细解释为什么需要使用`nonlocal`以及它的作用是什么?
▷🦆
你提到如果`当前节点自身是 p 或 q,或其任一子树包含 p 或 q,该节点会向其父节点报告这一发现`,这是如何通过代码实现的?具体在哪一部分代码中反映?
▷🦆
递归函数在发现`左右子树各找到一个目标节点`时就会设置`res`为当前节点并返回,这个逻辑是否意味着递归调用会在找到答案后立即停止?还是会继续执行其他分支的递归调用?
▷