比如:在如图这棵二叉树中,8和9的公共祖先是1,4和5的公共祖先是2,5和2的公共祖先是2。
在上述分析中,我们可以得出思路,本题解法可分为两种情况,(1)两个节点在根节点同侧 ,则它们的最近公共祖先可能是其中一个节点,也可能是在到两个节点的公共路径上。
(2)两个节点在根节点的不同侧,则它们的公共祖先只能是根节点。
同时,这棵树又分为三种情况:
(1)这棵树是搜索树
(2)这棵树中有三叉链
(3)它只是一棵普通的二叉树
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
BinaryTreeNode(const T& x)
:_data(x)
, _left(NULL)
, _parent(NULL)
, _right(NULL)
{}
};
1,这棵树是搜索树:根据搜索树的性质,它的所有左子树小于根节点,所有右子树大于根节点。
时间复杂度O(N)
Node* GetCommonAncestor(Node* root,Node* x1, Node* x2)
{
if (root == NULL)
return NULL;
else if ((x1->_data >= root->_data && x2->_data <= root->_data)
|| (x1->_data <= root->_data && x2->_data >= root->_data))
return root;
else if (x1->_data < root->_data && x2->_data < root->_data)
GetCommonAncestor(root->_left, x1, x2);
else if (x1->_data > root->_data && x2->_data > root->_data)
GetCommonAncestor(root->_right, x1, x2);
}
2,普通二叉树
时间复杂度O(N^2)
Node* GetCommonAncesstor(Node* root, Node* x1,Node*x2)
{
if (root == NULL)
return NULL;
if (x1 == NULL || x2 == NULL)
return NULL;
else
{
bool X1Inleft, X1Inright, X2Inleft, X2Inright;
X1Inleft = GetCommonAncesstor(root->_left, x1);
X1Inright = GetCommonAncesstor(root->_right, x1);
assert(X1Inleft || X1Inright);
X2Inleft = GetCommonAncesstor(root->_left, x1);
X2Inright = GetCommonAncesstor(root->_right, x2);
assert(X2Inleft || X2Inright);
if (X1Inleft&&X2Inleft)
return GetCommonAncesstor(root->_left, x1, x2);
if (X1Inright&&X2Inright)
return GetCommonAncesstor(root->_right, x1, x2);
else
return root;
}
}
优化为O(N)
Node* GetNodePath(Node* root,stack<Node*>& s, Node* x)
{
if (root)
s.push(root);
if (root->_data == x1->_data)
return true;
bool left = GetNodePath(root->_left, s, x);
if (left)
return true;
bool right = GetNodePath(root->_right, s, x);
if (right);
return true;
s.pop();
return false;
}
Node* GetNodeAncestor(Node* root, Node* x1, Node* x2)
{
if (NULL == root)
return NULL;
assert(x1 && x2);
stack<Node*> s1, s2;
if (!GetNodePaths(root, s1, x1) || !GetNodePaths(root, s2, x2))
return NULL;
while (s1.size() != s2.size())
{
if (s1.size() > s2.size())
s1.pop();
if (s1.size() < s2.size())
s2.pop();
}
while (!s1.empty() && !s2.empty() && s1.top() != s2.top())
{
s1.pop();
s2.pop();
}
return s1.top();
}
3,这棵二叉树中有三叉链
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
BinaryTreeNode<T>* _parent;
BinaryTreeNode(const T& x)
:_data(x)
, _left(NULL)
, _parent(NULL)
, _right(NULL)
{}
};
Node* GetCommenAncesstor(Node* root, Node* x1, Node* x2)
{
stack<Node*> s1;
stack<Node*> s2;
Node* cur1 = x1;
Node* cur2 = x2;
while (cur1->_parent)
{
if (cur1->_parent->_data == cur2->_data)
return cur;
else
s1.push(cur1);
cur1 = cur1->_parent;
}
while (cur2->_parent)
{
if (cur2->_parent->_data == cur1->_data)
return cur1;
else
s2.push(cur2);
cur2 = cur2->_parent;
}
Node* node = NULL;
while (!s1.empty() && !s2.empty())
{
if (s1.pop() == s2.pop())
node = s1.pop();
else
return node;
s1.pop();
s2.pop();
}
return node;
}