题目:设计并实现一个算法,找出二叉树中某两个结点的第一个共同祖先。不得将额外的结点存储在另外的数据结构中。注意,这不一定是二叉查找树。
解法:如果两个结点都在树中,且其中一个为根结点,那么直接返回根结点。接下来判断两个结点是否在根结点的同一个子树中,如果不同时在根结点的左子树或者右子树中,则根结点是第一个祖先,直接返回根结点。如果同在根结点的左子树中,递归判断两个结点在左子树中的第一个共同祖先。右子树时同样如此。另外程序一开始就需要判断两个结点是不是在二叉树中。
bool Covers(BinaryTreeNode* pRoot, BinaryTreeNode* pNode)
{
if(pRoot == NULL)
return false;
if(pRoot == pNode)
return true;
return Covers(pRoot->m_pLeft, pNode) || Covers(pRoot->m_pRight, pNode);
}
BinaryTreeNode* CommonAncestorCore(BinaryTreeNode* pRoot, BinaryTreeNode* pNode1, BinaryTreeNode* pNode2)
{
if(pRoot == NULL)
return NULL;
if(pRoot == pNode1 || pRoot == pNode2)
return pRoot;
bool node1InLeft = Covers(pRoot->m_pLeft, pNode1);
bool node2InLeft = Covers(pRoot->m_pLeft, pNode2);
if(node1InLeft != node2InLeft)
return pRoot;
BinaryTreeNode* newRoot = node1InLeft ? pRoot->m_pLeft : pRoot->m_pRight;
return CommonAncestorCore(newRoot, pNode1, pNode2);
}
BinaryTreeNode* CommonAncestor(BinaryTreeNode* pRoot, BinaryTreeNode* pNode1, BinaryTreeNode* pNode2)
{
if(!Covers(pRoot, pNode1) || !Covers(pRoot, pNode2))
return NULL;
return CommonAncestorCore(pRoot, pNode1, pNode2);
}