给定一个二叉树的根节点 root
和两个节点p
和q
,请找到这两个节点的最近公共祖先。最近公共祖先定义为:在二叉树中,p
和q
的最近公共祖先是一个节点,该节点是p
和q
的最低祖先节点,即p
和 q
都是这个节点的子孙(子孙的定义包括自己)。
root
p
和q
返回最近公共祖先节点
root = [3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]
p = 5
q = 1
二叉树的结构
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
3
这道题目要求找到二又树中两个节点 p
和q
。的最近公共祖先。最直接的思路是通过递归遍历树的方法来解决这个问题。我们可以采用“自底向上”的递归方式,检查每个节点,看看它是否是p
和 q
的公共祖先。
核心思路如下:
如果当前结点为null
,返回 null
。
如果当前结点是p
或q
,那么它就是其中一个节点的祖先,返回当前结点。
递归检查当前结点的左右孩子,分别在左右子树中搜索p
和q
。
根据左右子树的搜索结果:
•如果左右子树同时返回非空,说明p
和 q
分别位于当前结点的左右子树,当前结点即为最近公共祖先。
•如果只有一个子树返回非空,说明p
和 q
都在那个子树(或者其中一个在子树,一个就是当前结点),返回该非空的子树节点。
// 定义二叉树节点
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
// 求二叉树根节点root中节点p和q的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 如果当前节点为空,或者当前节点是p或q,则返回当前节点
// 这意味着我们找到了p、q其中之一,或者到达了树的末端
if (root == null || root == p || root == q) {
return root;
}
// 递归寻找p和q在左子树中的最近公共祖先
TreeNode left = lowestCommonAncestor(root.left, p, q);
// 递归寻找p和q在右子树中的最近公共祖先
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
if (left != null && right != null) {
return root;
}
// 如果只有左子树找到一个p或q,则返回左子树的结果(可能是p或q)
// 如果只有右子树找到一个p或q,则返回右子树的结果(可能是p或q)
return left != null ? left : right;
}
}
# 定义二叉树节点类
class TreeNode:
def __init__(self, x):
self.val = x # 节点的值
self.left = None # 左子树
self.right = None # 右子树
class Solution:
# 求二叉树root中节点p和q的最近公共祖先
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
# 如果当前节点为空,或者当前节点是p或q,直接返回当前节点
if not root or root == p or root == q:
return root
# 在左子树中递归寻找p和q的最近公共祖先
left = self.lowestCommonAncestor(root.left, p, q)
# 在右子树中递归寻找p和q的最近公共祖先
right = self.lowestCommonAncestor(root.right, p, q)
# 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
if left and right:
return root
# 如果只有左子树找到一个p或q,则返回左子树的结果(可能是p或q)
# 如果只有右子树找到一个p或q,则返回右子树的结果(可能是p或q)
return left if left else right
// 定义二叉树节点结构体
struct TreeNode {
int val; // 节点的值
TreeNode *left; // 左子树
TreeNode *right; // 右子树
// 构造函数
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
// 求二叉树root中节点p和q的最近公共祖先
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 如果当前节点为空,或者当前节点是p或q,直接返回当前节点
// 这意味着我们找到了p、q其中之一,或者到达了树的末端
if (root == nullptr || root == p || root == q) {
return root;
}
// 在左子树中递归寻找p和q的最近公共祖先
TreeNode* left = lowestCommonAncestor(root->left, p, q);
// 在右子树中递归寻找p和q的最近公共祖先
TreeNode* right = lowestCommonAncestor(root->right, p, q);
// 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
if (left != nullptr && right != nullptr) {
return root;
}
// 如果左子树找到一个p或q,则返回左子树的结果(可能是p或q)
// 如果右子树找到一个p或q,则返回右子树的结果(可能是p或q)
return left != nullptr ? left : right;
}
};