分析:
1.二叉树是 二叉搜索树(左节点小于父节点,右节点大于父节点)
思路:从根节点开始,如果当前节点比两个节点都大,则在左子树;如比当前节点都小,则在右子树
以此类推,直到找到一个节点的大小介于两节点之间,则该节点就是最近的公共父节点
2.非二叉搜索树,但有指向父节点的指针域
思路:分别从两个节点开始得到其返回根节点的路径(链表),在这两条路径中找到第一个公共节点
3.普通二叉树
思路1. 如果在节点的左边包含两个目标节点,则进入左节点;如果在节点的右边包含两个目标节点,则进入右节点;
退出条件:如果两目标节点不在该节点的同一侧,则该节点就是要找的
思路2. 思路1比较慢;我们可以分别得到根节点到两目标节点的路径,则问题转化为链表的最后一个公共节点
代码实现:
typedef struct BtNode
{
int val;
struct BtNode* left;
struct BtNode* right;
};
bool GetNodePath(BtNode* pRoot, BtNode* pNode, list<BtNode*> path) //得到路径
{
if (pRoot == pNode)
return true;
bool found = false;
if (pRoot != NULL && pNode != pRoot) //还没遍历到空,且不相等
{
path.push_back(pRoot);
found = GetNodePath(pRoot->left, pNode, path);
if (found)
return found;
found = GetNodePath(pRoot->right, pNode, path);
}
if (!found)
path.pop_back();
return found;
}
BtNode* GetLastCommentNode(list<BtNode*> path1, list<BtNode*> path2) //比较两个路径
{
list<BtNode*>::const_iterator iterator1 = path1.begin();
list<BtNode*>::const_iterator iterator2 = path1.begin();
BtNode* pNext = NULL;
while (iterator1 != path1.end() && iterator2 != path2.end())
{
if (*iterator1 == *iterator2)
pNext = *iterator1;
iterator1++;
iterator1++;
}
return pNext;
}
BtNode* GetLastCommonParent(BtNode* pRoot, BtNode* pNode1, BtNode* pNode2) //调用上述两个得到结果
{
if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
return NULL;
list<BtNode*> path1;
GetNodePath(pRoot, pNode1, path1);
list<BtNode*> path2;
GetNodePath(pRoot, pNode2, path2);
return GetLastCommentNode(path1,path2);
}