二叉树中两个节点的最低公共祖先

原创 2016年05月31日 20:10:34

1、如果此二叉树为二叉搜索树,即树中所有结点的左子树的结点都比父结点小,所有结点的右子树都比父结点大

  对于此种情况,我们只需从树的根结点开始和输入的两个结点进行比较。如果当前结点的值比两个结点的值都大,那么最低的共同父结点一定是在当前结点的左子树中,于是下一步遍历当前结点的左子结点;如果当前结点的值比两个结点的值都小,那么最低的共同父结点一定是在当前结点的右子树中,于是下一步遍历当前结点的右子结点。这样在树中从上到下找到第一个在输入结点的值之间的结点,就是最低的公共祖先。

struct BSNode
{
	int _data;
	BSNode* _left;
	BSNode* _right;
	BSNode(int data = 0) :_data(data), _left(NULL), _right(NULL)
	{}
};
BSNode* GetLastCommonParent_1(BSNode* pRoot, BSNode* pNode1, BSNode* pNode2)
{
	if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
	{
		return NULL;
	}
	if (pNode1 == pNode2)
	{
		return pNode1;
	}
	BSNode* cur = pRoot;
	while (true)
	{
		if ((cur->_data >= pNode1->_data&&cur->_data<=pNode2->_data) ||
		(cur->_data>=pNode2->_data&&cur->_data <= pNode1->_data))
			return cur;
		else if (cur->_data>pNode1->_data)
		{
			cur = cur->_left;
		}
		else
		{
			cur = cur->_right;
		}
	}
	return NULL;
}

2、如果此树是含有父结点的二叉树

对于此种情况,可以转化为求两个链表的第一个公共结点。假设树结点中指向父结点的指针是_parent,那么从树每一结点开始都有一个由_parent串起来的链表,这些链表的尾指针都是根结点。输入两个结点,那么这两个结点位于两个链表上,它们的最低公共祖先刚好就是这两个链表的第一个公共结点。

struct BinTreePar
{
	int _data;
	BinTreePar* _left;
	BinTreePar* _right;
	BinTreePar* _parent;
	BinTreePar(int data = 0) :_data(data), _left(NULL), _right(NULL), _parent(NULL)
	{}
};
//求到根结点的路径长度
int BinLen(BinTreePar* pRoot, BinTreePar* pNode)
{
	int count = 0;
	BinTreePar* cur = pNode;
	while (cur != pRoot)
	{
		++count;
		cur = cur->_parent;
	}
	return count;
}
BinTreePar* GetLastCommonParent_2(BinTreePar* pRoot, BinTreePar* pNode1, BinTreePar* pNode2)
{
	if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
	{
		return NULL;
	}
	if (pNode1 == pNode2)
	{
		return pNode1;
	}
	//类似相交单链表找相遇点
	BinTreePar* curA = pNode1;
	BinTreePar* curB = pNode2;

	//计算到根节点的距离
	int lenA = BinLen(pRoot, pNode1);
	int lenB = BinLen(pRoot, pNode2);
	int subLen = lenA - lenB;
	if (subLen > 0)
	{
		while (subLen--)
		{
			curA = curA->_parent;
		}
	}
	else if (subLen < 0)
	{
		while (subLen++)
		{
			curB = curB->_parent;
		}
	}
	while (curA != curB)
	{
		curA = curA->_parent;
		curB = curB->_parent;
	}
	return curA;
}
3、此树是普通的二叉树
      对于此种情况,我们需找到从根节点到输入的两个的路径,然后有辅助的内存来保存路径,然后再从这两条路径中找出最后一个相同的结点。

#include <list>
struct BinTree
{
	int _data;
	BinTree* _left;
	BinTree* _right;
	BinTree(int data = 0) :_data(data), _left(NULL), _right(NULL)
	{}
};
//寻找路径
bool FindRoot(BinTree* pRoot, BinTree* pNode, list<BinTree*>& listRoot)
{
	if (pRoot == NULL || pNode == NULL)
	{
		return true;
	}
	listRoot.push_back(pRoot);
	if (pRoot == pNode)
	{
		return true;
	}
	if (pRoot->_left)
	{
		bool ret = FindRoot(pRoot->_left, pNode, listRoot);
		if (ret)
		{
			return true;
		}
	}
	if (pRoot->_right)
	{
		bool ret = FindRoot(pRoot->_right, pNode, listRoot);
		if (ret)
		{
			return true;
		}
	}
	listRoot.pop_back();
}
BinTree* GetLastCommonParent_3(BinTree* pRoot, BinTree* pNode1, BinTree* pNode2)
{
	//找到由根节点到pNode1、pNode2的路径,再找最后一个相同的结点,用list保存路径
	if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
	{
		return NULL;
	}
	if (pNode1 == pNode2)
	{
		return pNode1;
	}
	list<BinTree*> listRoot1;
	list<BinTree*> listRoot2;
	FindRoot(pRoot, pNode1, listRoot1);
	FindRoot(pRoot, pNode2, listRoot2);
	list<BinTree*>::iterator iteA = listRoot1.begin();
	list<BinTree*>::iterator iteB = listRoot2.begin();
	BinTree* ret = listRoot1.front();
	list<BinTree*>::iterator end = listRoot1.end();
	
	while (iteA != listRoot1.end() && iteB != listRoot2.end() && (*iteA)->_data == (*iteB)->_data)
	{
		ret = *iteA;
		++iteA;
		++iteB;
	}
	return ret;
}




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

面试题50:二叉树中两个节点的最低公共祖先

#include #include #include using namespace std; typedef struct BtNode { int value; struct Bt...
  • damotiansheng
  • damotiansheng
  • 2016年05月31日 20:24
  • 647

剑指offer 面试题50—树中两个节点的最低公共祖先

#include #include #include using namespace std; typedef struct TreeNode { int data; ...
  • wtyvhreal
  • wtyvhreal
  • 2015年05月07日 19:23
  • 1891

求树中两个节点的最低公共祖先

情形1:树是搜索二叉树 思路:从树的根节点开始遍历,如果根节点的值大于其中一个节点,小于另外一个节点,则根节点就是最低公共祖先。否则如果根节点的值小于两个节点的值,则递归求根节点的右子树,如果大...
  • jingshuigg
  • jingshuigg
  • 2014年06月15日 22:31
  • 2264

树——在二叉树中找到两个节点的最低公共祖先LCA

首先利用自底向上的思路——如果遍历到当前节点是A/B中的任意一个,则向父节点汇报此节点,否则递归到节点为null时返回null值。 具体情况如下几种: 1.当前节点即为两个节点中的一个,此时直接向...
  • jingsuwen1
  • jingsuwen1
  • 2016年07月30日 10:44
  • 220

二叉树中查找两个节点的最低公共祖先

这是一道企业面试中,经常会被问到的面试题目。 在网上看到一些此题的实现,其中有两种方法是比较适合编程的。本项目的源代码,请点击这里下载。 方法一:   此方法是根据二叉树的DFS查找并标记祖先,...
  • fy2462
  • fy2462
  • 2014年06月17日 14:24
  • 2251

《剑指offer》:[50]树中两个结点的最低公共祖先结点

题目:树中两个结点的最低公共祖先 该题目根据条件的不同,所使用的方案也不同。 条件一:是二叉搜索树。      方案:这种情况相对来说是最简单的,如果是二叉搜索树,则树里的数据特点比较明显。左边的比根...
  • gogoky
  • gogoky
  • 2016年06月25日 15:32
  • 912

麒麟远创面试题3:二叉树中求两个节点的最低公共祖先节点

题目要求:求二叉树中两个节点p,q的最低公共祖先节点
  • chosen0ne
  • chosen0ne
  • 2011年01月11日 20:54
  • 4499

求二叉树中两个节点的最近公共祖先结点

二叉树是搜索二叉树 1、原理:二叉搜索树是排序过的 ,位于左子树的结点都比父结点小,位于右子树的结点都比父结点大,我们只需从根节点开始和两个输入的结点进行比较,如果当前节点的值比两个结点的值都大,那么...
  • xiaocherry1128
  • xiaocherry1128
  • 2017年07月29日 16:26
  • 1548

剑指Offer之 - 树中两个结点的最低公共祖先

题目: 求树中两个节点的最低公共祖先。 思路一: ——如果是二叉树,而且是二叉搜索树,那么是可以找到公共节点的。 二叉搜索树都是排序过的,位于左子树的节点都比父节点小,而位于右子树上面的节点都比...
  • u012243115
  • u012243115
  • 2015年04月29日 16:07
  • 547

剑指Offer(第二版)面试案例:树中两个节点的最低公共祖先节点

树中两个节点的最低公共祖先节点
  • qq_25827845
  • qq_25827845
  • 2017年07月06日 22:03
  • 1546
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树中两个节点的最低公共祖先
举报原因:
原因补充:

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