问题:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
思路:
第一步,找到根到两个节点的路径
第二步,找到两个路径的最后一个公共节点
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool getNodePath(TreeNode* root,TreeNode* p,list<TreeNode*>& path)
{
path.push_back(root);
if(root==p)
return true;
bool found=false;
if(!found&&root->left)
{
found=getNodePath(root->left,p,path);
}
if(!found&&root->right)
{
found=getNodePath(root->right,p,path);
}
if(!found)
path.pop_back();
return found;
}
TreeNode* getLastCommonNode(list<TreeNode*> path1,list<TreeNode*> path2)
{
list<TreeNode*>::iterator i=path1.begin();
list<TreeNode*>::iterator j=path2.begin();
TreeNode* pLast=nullptr;
while(i!=path1.end()&&j!=path2.end())
{
if(*i==*j)
pLast=*i;
i++;
j++;
}
return pLast;
/*int len1=path1.size();
int len2=path2.size();
TreeNode* pLast=nullptr;
int i=0,j=0;
while(i<len1&&j<len2)
{
if(path1[i]==path2[j])// list[i] need O(n)
pLast=path1[i];
++i;
++j;
}*/
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==nullptr||p==nullptr||q==nullptr)
return nullptr;
list<TreeNode*> path1;
getNodePath(root,p,path1);
list<TreeNode*> path2;
getNodePath(root,q,path2);
return getLastCommonNode(path1,path2);
}
};
复杂度分析:时间复杂度为O(n),空间复杂度为O(logn).