题目:
输入两个树节点,求他们的最低公共祖先。
- 二叉树(二叉搜索树):二叉搜索树是排序的,如果当前节点大于两个节点的值,去左子树中寻找;如果当前节点小于两个节点的值,去右子树中寻找;如果当前节点位于两个节点值之间,则该节点就是要寻找的最低公共祖先。
- 普通树(存在指向父节点的指针):从给定节点出发,由父节点指针回到到根结点,形成链表。从而将问题转化为求两个链表的第一个公共节点的问题。
- 普通树(不存在指向父节点的指针):利用两个辅助链表通过递归遍历的方法找到两条到达给定节点的路径,寻找两个链表最后一个公共节点,就是最低公共祖先。
链接:
剑指Offer(第2版):P326
思路标签:
- 公共子节点、链表、二叉搜索树
解答:
- 给出第三种方法的程序
- 普通树的子节点是一个vector数组,保存指向树节点的一系列指针。
struct TreeNode
{
int m_nValue;
std::vector<TreeNode*> m_vChildren;
};
bool GetNodePath(const TreeNode* pRoot, const TreeNode* pNode, list<const TreeNode*>& path)
{
if (pRoot == pNode)
return true;
path.push_back(pRoot);
bool found = false;
vector<TreeNode*>::const_iterator i = pRoot->m_vChildren.begin();
while (!found && i < pRoot->m_vChildren.end())
{
found = GetNodePath(*i, pNode, path);
++i;
}
if (!found)
path.pop_back();
return found;
}
const TreeNode* GetLastCommonNode(const list<const TreeNode*>& path1, const list<const TreeNode*>& path2)
{
list<const TreeNode*>::const_iterator iterator1 = path1.begin();
list<const TreeNode*>::const_iterator iterator2 = path2.begin();
const TreeNode* pLast = nullptr;
while (iterator1 != path1.end() && iterator2 != path2.end())
{
if (*iterator1 == *iterator2)
pLast = *iterator1;
iterator1++;
iterator2++;
}
return pLast;
}
const TreeNode* GetLastCommonParent(const TreeNode* pRoot, const TreeNode* pNode1, const TreeNode* pNode2)
{
if (pRoot == nullptr || pNode1 == nullptr || pNode2 == nullptr)
return nullptr;
list<const TreeNode*> path1;
GetNodePath(pRoot, pNode1, path1);
list<const TreeNode*> path2;
GetNodePath(pRoot, pNode2, path2);
return GetLastCommonNode(path1, path2);
}