力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
目录
题目名称 力扣236.二叉树最近的公共祖先
1.题目
2.题目分析
3.题目答案
最后
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
解法1
通过观察规律可得,如果一个节点在这个节点的左子树,另一个节点在这个节点的右子树,那么这个节点就是这两个节点的最近公共祖先。
通过Find判断这个节点在当前节点的左子树还是右子树,得到结果后进行判断。如果同时在其左子树或者右子树就进行递归转化,如果一个在左子树一个在右子树就直接返回。
解法2
可以把寻找二叉树节点最近公共祖先的问题转化为链表相交问题。只要找出这两个节点距离根节点的路径,然后再把这两个路径进行比较,后找出两个路径的第一个相同节点,就可以返回了。
这个寻找路径算法是重点,注意传参时stack传引用。如果这个节点对应的左右子树都没有符合条件的节点,那么就要将这个节点pop出队列,如果找到了就return true.
解法1 找规律
class Solution {
bool Find(TreeNode* root, TreeNode* p)
{
if (root == nullptr)
{
return false;
}
return (root == p) || (Find(root->left, p)) || (Find(root->right, p));
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr)
{
return nullptr;
}
if (root == p || root == q)
{
return root;
}
bool pInleft = Find(root->left, p);
bool pInright = !pInleft;
bool qInleft = Find(root->left, q);
bool qInright = !qInleft;
if ((pInleft && qInright) || (pInright && qInleft))
{
return root;
}
if (pInleft && qInleft)
{
return lowestCommonAncestor(root->left, p, q);
}
else
{
return lowestCommonAncestor(root->right, p, q);
}
}
}
解法2 转化为链表相交问题
class Solution {
bool Find(TreeNode* root, TreeNode* q, stack& st)
{
if (root == nullptr)
{
return false;
}
if (root == q)
{
st.push(root);
return true;
}
st.push(root);
if ((Find(root->right, q, st) == false) && (Find(root->left, q, st) == false))
{
st.pop();
return false;
}
else {
return true;
}
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//求路径
stack stp;
Find(root, p, stp);
stack stq;
Find(root, q, stq);
//求相交节点
while (stp.size() > stq.size())
{
stp.pop();
}
while (stp.size() < stq.size())
{
stq.pop();
}
while (stp.top() != stq.top())
{
stq.pop();
stp.pop();
}
return stp.top();
}
};
除夕快乐!!