1. 题目
2. 解法
解题思路
- 我们要找到两个指定节点的最近公共祖先,也就是说,我们要找到一个节点,它是两个指定节点的祖先,而且它的深度尽可能大。
- 为了找到这样的节点,我们可以从根节点开始,递归地遍历二叉树,判断每个节点是否满足这个条件。
- 如果一个节点满足这个条件,那么它必须同时满足以下两个子条件:
- 它本身是两个指定节点之一,或者它的左子树和右子树分别包含两个指定节点。
- 它的左子树和右子树中没有其他节点满足这个条件,也就是说,它是最深的满足条件的节点。
- 因此,我们可以定义一个递归函数,它接受一个根节点和两个目标节点作为参数,返回这三个节点的最近公共祖先。如果不存在这样的祖先,就返回空。
- 在递归函数中,我们首先判断根节点是否为空,或者是否等于其中一个目标节点。如果是,就直接返回根节点,因为它就是最近公共祖先。
- 然后,我们递归地调用这个函数,分别对根节点的左子树和右子树进行遍历,得到两个返回值,分别表示左子树和右子树中是否存在目标节点。
- 最后,我们根据左右子树的返回值来判断最近公共祖先是谁。有三种情况:
- 如果左右子树都不为空,说明两个目标节点分别在根节点的两侧,那么根节点就是最近公共祖先。
- 如果左子树为空,说明两个目标节点都在右子树中,那么右子树的返回值就是最近公共祖先。
- 如果右子树为空,说明两个目标节点都在左子树中,那么左子树的返回值就是最近公共祖先。
这样,我们就可以通过递归遍历二叉树,找到两个指定节点的最近公共祖先了。
具体实现
// 定义二叉树节点 class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } // 解决方法 class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { // 如果根节点为空,或者找到了p或q,返回根节点 if (root == null || root == p || root == q) return root; // 递归遍历左子树 TreeNode left = lowestCommonAncestor(root.left, p, q); // 递归遍历右子树 TreeNode right = lowestCommonAncestor(root.right, p, q); // 如果左右子树都不为空,说明当前节点就是最近公共祖先 if (left != null && right != null) return root; // 如果左子树为空,返回右子树 if (left == null) return right; // 如果右子树为空,返回左子树 return left; } }
3. 总结