最低公共祖先问题的求解

原创 2016年08月30日 21:28:14

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)。所以将你的解法概括为算法能够解决一类问题,每一步都很关键。但要大胆地迈出那一步,去不断总结,不断套路(动态规划),不断成长。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

洛谷3379 最近公共祖先

dfs+并查集求LCA
  • sdfzyhx
  • sdfzyhx
  • 2016年10月19日 20:44
  • 298

求两个节点的最近公共祖先节点

分三种情况 1、搜索二叉树,根据搜索二叉树的性质,左子树的所有节点比根节点小,右子树的所有节点比跟节点大。 如果两个节点都比根节点小,则递归左子树 如果两个节点都比跟节点大,则递归右子树 否则...

剑指offer50:求两个节点的最低公共祖先

该题可转化为求俩个链表的公共节点,求出根节点到两个节点的路径,将路径转化为链表,最近的公共节点就是最低公共祖先。 public class offer50 { class TreeNode{...

java的Timer计时器实现几秒后循环执行代码的例子

package my.test.timer; import java.util.Timer; import java.util.TimerTask; /*  * 让程序在启用Timer 100...
  • remgoo
  • remgoo
  • 2011年11月04日 16:45
  • 3064

有向图强连通分量 Tarjan算法【java实现】

注:本文章上部分内容转载自http://www.cppblog.com/sosi/archive/2010/09/26/127797.html;一方面是网上有很多关于tarjan算法的介绍,我觉得都没...

最低公共祖先问题

问题1:求平衡二叉树的最低公共祖先。 问题2:求普通二叉树的最低公共祖先。 问题3:求普通树的最低公共祖先。 代码如下:   问题1: #include using namespace ...

利用二叉树的非递归后序遍历求解最近公共祖先问题

通过上一篇的博客我们知道,可以利用栈来实现二叉树的后序遍历。其实这里有一个性质,就是当使用非递归后序遍历时,栈中的元素就是当前节点到根节点的路径。利用这个规律,我们就可以求解最近公共最先问题了。 算法...
  • Ajay666
  • Ajay666
  • 2017年08月05日 22:38
  • 272

[Tarjan算法]最近公共祖先(LCA)问题求解

想了一想几个月前打的用于解LCA的Tarjan貌似弃坑就没再管它,然后虚拟机磁盘被我莫名其妙起爆了以后之前打的程序全都打了水漂就想起了被置之不理的Tarjan解LCA问题的板子,索性就把坑填上呗,毕竟...

二叉树(12)----查找两个节点最低祖先节点(或最近公共父节点等),递归和非递归

1、二叉树定义: typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:最低公共祖先问题的求解
举报原因:
原因补充:

(最多只允许输入30个字)