您的位置:首页 > 其它

最低公共祖先问题的求解

2016-08-30 21:28 190 查看
1.树的公共祖先问题

       首先明确一下这里的公共祖先的概念。所谓公共祖先,就是两节点位于不同分支或者同一分支,最近的公共的父节点(说父节点不太准确,可能是祖父节点等)。

       我们先不考虑算法,让我们自己找两个节点的最低公共祖先,我们应该是要按照路径找到两个节点,然后看两条路径的交点。很好,我们自下而上找交点是我们解决问题的思想。

       变形1:我们可以从根节点遍历,若左子节点为根的左子树包含两个节点,则递归至左子树;若右子节点为根的右子树包含两个节点则递归至右子树。否则直接返回根节点。

       注:此时树要是二叉搜索树,可以比较节点值的大小来进行变形1的计算。

       若此时有指向父节点的指针,则从两个节点出发,问题转化为求两个链表的交点。

       变形2:这个更加符合我们的思路,直接找到到两个节点的路径,求得路径的交点。

       变形2的参考代码如下:

#include<iostream>
#include<list>
#include<vector>
using namespace std;

struct TreeNode
{
int value;
vector<TreeNode *>m_vChildren;
};

bool GetNodePath(TreeNode *pRoot,TreeNode *pNode,list<TreeNode *>&path)
{
if(pRoot==pNode)
return true;
path.push_back(pRoot);
bool found=false;
vector<TreeNode *>::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;
}

TreeNode *GetLastCommonNode(list<TreeNode *>&path1,list<TreeNode *>&path2)
{
list<TreeNode *>::iterator i1=path1.begin();
list<TreeNode *>::iterator i2=path2.begin();

TreeNode *node=NULL;
while(i1!=path1.end()&&i2!=path2.end())
{
if(*i1==*i2)
node=*i1;
i1++;
i2++;
}
return node;
}

TreeNode *GetLastCommonParent(TreeNode *pRoot,TreeNode *pNode1,TreeNode *pNode2)
{
if(pRoot==NULL||pNode1==NULL||pNode2==NULL)
return NULL;
list<TreeNode *>path1;
list<TreeNode *>path2;
GetNodePath(pRoot,pNode1,path1);
GetNodePath(pRoot,pNode2,path2);
return GetLastCommonNode(path1,path2);
}

       代码是以多叉树的结构来写的。

       之所以写这篇文章,是因为我们自己都会找最低公共祖先。但同时转化为程序、算法就显得有些吃力。其实这些还是人的解决方法一步步转化、提炼、优化。这个思路的过程:

       自己的解决办法---->转化为算法

       我之前有文章所说的不要自己凭空制造规则,所谓规则就是算法。我曾经为求简单,制造简单的规则是满足case较少的情况,但对于问题的解决没什么用。(自己制造的规则仅满足case1)。所以将你的解法概括为算法能够解决一类问题,每一步都很关键。但要大胆地迈出那一步,去不断总结,不断套路(动态规划),不断成长。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息