要求考虑以下三种种情况,给出解决方案,并解决:
1:二叉树是搜索二叉树。
2: 二叉树每个节点有parent(三叉链)
3:就是普通二叉树。(尽可能实现时间复杂度为O(N))
针对第一种情况,是一棵二叉搜索树,我们可以根据数据的大小来判断两个节点的位置,如果在根节点的2侧,则根节点为最近公共祖先,如果在根节点的同侧,继续寻找2个节点的位置
TreeNode* PublicLowParent(TreeNode *root, TreeNode*c1, TreeNode* c2)
{
if (root == NULL)
return NULL;
TreeNode* cur = root;
while (cur)
{
if (c1->data > cur->data&&c2->data > cur->data)
{//x1,x2都在右子树
cur = cur->right;
}
else if (c1->data < cur->data&&c2->data < cur->data)
{//x1,x2都在左子树
cur = cur->left;
}
else
return cur;
}
}
针对第二种情况
以前遇到过2个单链表相交求交点的问题,此时我们可以借鉴当时的链表求交点的办法,来寻找2个节点所在链表的交点,即为公共最近公共祖先。链表求交点,如果2个链表长度不相等,要将长链表缩短,直到与短链表的长度相等为止。
int GetLen(TreeNode *root,TreeNode* node)
{
int count = 0;
if (node == root)
return 0;
while (node != root)
{
count++;
node = node->parent;
}
return count;
}
TreeNode* PublicLowParent(TreeNode *root, TreeNode*c1,TreeNode* c2 )
{
TreeNode* p1 = c1;
TreeNode* p2 = c2;
int len1 = GetLen(root,c1);
int len2 = GetLen(root,c2);
int sz = len1 - len2;
//p1比p2长,p1先走多余的长度步
if (sz > 0)
{
while (sz--)
{
p1 = p1->parent;
}
}
//p2比p1长,p2先走多余的长度步
else
{
sz = 0 - sz;
while (sz--)
{
p2 = p2->parent;
}
}
//此时链表长度一样,一起向后走
while (p1 != p2)
{
p1 = p1->parent;
p2 = p2->parent;
}
//跳出循环时即为2链表相交点
return p1;
}
对于第三种情况,我们借助栈来实现,保存这2个节点从根结点开始到他们的路径,根据栈中的数据来判断最近的公共交点,同样也用到了链表的求交点的思想
//从根结点开始找寻节点,将路径中的节点分别进行压栈
bool GetPath(TreeNode* root, TreeNode* node, stack<TreeNode*>& s)
{
if (root == NULL)
return false;
s.push(root);
if (root == node)
return true;
else //node != root
{
bool x = GetPath(root->left,node,s);
bool y = GetPath(root->right, node, s);
if (x==false&&y==false)//没有找到节点,弹出
{
s.pop();
return false;
}
return true;
}
}
TreeNode* PublicLowParent(TreeNode *root, TreeNode*c1, TreeNode* c2)
{
if (root == NULL)
return NULL;
stack<TreeNode*>s1;//保存c1的路径
stack<TreeNode*>s2;//保存c2的路径
GetPath(root, c1, s1);
GetPath(root, c2, s2);
if (s1.empty() || s2.empty())
return NULL;
//两个栈中元素个数之差
int sz = s1.size() - s2.size();
//类似2个链表求交点
if (sz > 0)
{
while (sz--)
{
s1.pop();
}
}
else
{
sz = 0 - sz;
while (sz--)
{
s2.pop();
}
}
while (!s1.empty() && !s2.empty() && s1.top() != s2.top())
{
s1.pop();
s2.pop();
}
return s1.top();
}