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

原创 2016年05月31日 20:24:29
<pre name="code" class="plain"><span style="font-size:14px;">#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


typedef struct BtNode
{
	int value;
	struct BtNode *lchild;
	struct BtNode *rchild;
}BtNode, *Bitree;

Bitree newBtNode()
{
	Bitree p = new BtNode;

	if( NULL == p )
	{
		cout << "newBtNode func: err -1, NULL==p " << endl;
		return p;
	}

	p->value = 0;
	p->lchild = p->rchild = NULL;
	return p;
}


int createBitree( Bitree *head )
{
	int ret = 0;

	if( NULL == head )
	{
		cout << "createBitree func: err -1, NULL==head" << endl;
		ret = -1;
		return ret;
	}

	int data = 0;
	cin >> data;
	
	if( 0 == data ) // leaf
	{
		*head = NULL;
	}
	else
	{
		*head = newBtNode();
		(*head)->value = data;
		createBitree( &( (*head)->lchild ) );
		createBitree( &( (*head)->rchild ) );
	}


	return ret;
	
}

void preTravel( Bitree head )
{
	if( head != NULL )
	{
		cout << head->value << ' ';
		preTravel( head->lchild );
		preTravel( head->rchild );
	}

	return;
}

void midTravel( Bitree head )
{
	if( head != NULL )
	{
		midTravel( head->lchild );
		cout << head->value << ' ';
		midTravel( head->rchild );
	}

	return;
}

void postTravel( Bitree head )
{
	if( head != NULL )
	{
		postTravel( head->lchild );
		postTravel( head->rchild );
		cout << head->value << ' ';
	}

	return;
}

// 找出二叉树中的两个结点的最低公共祖先
Bitree findLastCommonNode( Bitree head, int value1, int value2 )
{
	Bitree pRet = NULL;

	if( NULL == head )
	{
		cout << "findLastCommonNode func: err -1, NULL==head" << endl;
		return pRet;		
	}

	
	if( ( value1 < head->value && head->value < value2 ) || ( value2 < head->value && head->value < value1 ) )
	{
		pRet = head;
		return pRet;
	}
	else if( head->value > value1 && head->value > value2 ) // 当前节点比要找的两个节点的值大,从左子树递归查找
	{
		if( NULL == head->lchild )
		{
			cout << "findLastCommonNode func: can not find the two nodes in bitree" << endl;
			return pRet;
		}
	
		return findLastCommonNode( head->lchild, value1, value2 );
	}
	else if( head->value < value1 && head->value < value2 ) // 当前节点比要找的两个节点的值小,右子树递归查找
	{
		if( NULL == head->lchild )
		{
			cout << "findLastCommonNode func: can not find the two nodes in bitree" << endl;
			return pRet;
		}

		return findLastCommonNode( head->rchild, value1, value2 );
		
	}
	
	cout << "findLastCommonNode func: err, value1 = " << value1 << ", value2 = " << value2 << endl;

	return pRet;
}


// 在二叉树中查找是否存在该节点
Bitree checkIsInBiTree( Bitree root, int value )
{
	Bitree pTarget = NULL;

	if( NULL == root )
	{	
		cout << "checkIsInBiTree( Bitree root, int value ) func: err -1, NULL==root, value = " << value << endl;
		return pTarget;
	}

	if( root->value == value )
	{
		pTarget = root;
		return pTarget;
	}
	else if( root->value < value && root->rchild != NULL )
	{
		return checkIsInBiTree( root->rchild, value );
	}
	else if( root->value > value && root->lchild != NULL )
	{
		return checkIsInBiTree( root->lchild, value );
	}
	else
	{
		return pTarget;
	}
}


int checkValid( Bitree root, int value1, int value2, Bitree *pFirstNode )
{
	int ret = 0;

	if( NULL == root || NULL == pFirstNode )
	{
		cout << " checkValid func: err -1,NULL == root || NULL == pFirstNode " << endl;
		ret = -1;
		return ret;
	}
	

	if( value1 == value2 )
	{
		Bitree p1 = checkIsInBiTree( root, value1 );

		if( NULL == p1 )
		{
			ret = -1;
			return ret;
		}
		else
		{
			Bitree p2 = NULL;

			if( p1->lchild != NULL )
			{
				p2 = checkIsInBiTree( p1->lchild, value2 );	
			}
			else if( p1->rchild != NULL )
			{
				p2 = checkIsInBiTree( p1->rchild, value2 );	
			}

			if( NULL == p2 )
			{
				ret = -1;
				return ret;
			}
			else
			{
				*pFirstNode = p1;
				ret = 1;  // value2节点是value1的子节点
			}
			
		}
	}
	else
	{
		Bitree p1 = checkIsInBiTree( root, value1 );
		Bitree p2 = checkIsInBiTree( root, value2 );

		if( NULL == p1 || NULL == p2 )
		{
			ret = -1;
			return ret;
		}

		//bool isChild = false;
		
		
		if( p1->lchild != NULL )
		{
			if( checkIsInBiTree( p1->lchild, value2 ) != NULL )
			{
				*pFirstNode = p1;
				ret = 1;	
			}
		}
		
		// 查找是否value1是value2的子节点,或value2是value1的子节点
		if( p1->rchild != NULL )
		{
			if( checkIsInBiTree( p1->rchild, value2 ) != NULL )
			{
				*pFirstNode = p1;
				ret = 1;	
			}
		}

		if( p2->lchild != NULL )
		{
			if( checkIsInBiTree( p2->lchild, value1 ) != NULL )
			{
				*pFirstNode = p2;
				ret = 1;	
			}
		}
		
		
		if( p2->rchild != NULL )
		{
			if( checkIsInBiTree( p2->rchild, value1 ) != NULL )
			{
				*pFirstNode = p2;
				ret = 1;	
			}
		}
		


	}

	return ret;
}

Bitree findParentOfChildByValue( Bitree root, int child )
{
	Bitree parent = NULL;

	if( NULL == root )
	{
		cout << "findParentOfChild func: err -1, NULL==root " << endl;
		return parent;
	}

	if( root->lchild != NULL && root->lchild->value == child )
	{
		parent = root;
		return parent;
	}	
	else if( root->rchild != NULL && root->rchild->value == child )
	{	
		parent = root;
		return parent;
	}
	else if( root->lchild != NULL && root->value > child )
	{
		return findParentOfChildByValue( root->lchild, child );
	}
	else if( root->rchild != NULL && root->value < child )
	{
		return findParentOfChildByValue( root->rchild, child );
	}
	else
	{
		return parent;
	}

}

Bitree findParentOfChildByPointer( Bitree root, Bitree child )
{
	Bitree parent = NULL;

	if( NULL == root || NULL == child )
	{
		cout << "findParentOfChildByPointer func: err -1, NULL==root || NULL == child " << endl;
		return parent;
	}

	if( root->lchild == child || root->rchild == child )
	{
		parent = root;
		return parent;
	}
	else if( root->lchild != NULL && root->value > child->value )
	{
		return findParentOfChildByPointer( root->lchild, child );
	}
	else if( root->rchild != NULL && root->value < child->value )
	{
		return findParentOfChildByPointer( root->rchild, child );
	}
	else
	{
		return parent;
	}
	
	
}
	

// 在二叉树(并不需要是排序二叉树)中查找value的节点,并返回指向该节点的指针,没找到返回NULL
Bitree getNodeByValue( Bitree root, int value )
{
	Bitree pRet = NULL;

	if( NULL == root )
	{
		cout << "getNodeByValue func: err -1, NULL==root" << endl;
		return pRet;		
	}	

	if( root->value == value )
	{
		pRet = root;
		return pRet;
	}
	else
	{
		Bitree pLeftResult = NULL;
		Bitree pRightResult = NULL;
		
		if( root->lchild != NULL )
		{
			pLeftResult = getNodeByValue( root->lchild, value );
		}

		if( pLeftResult != NULL ) // 找到了
		{
			pRet = pLeftResult;
			return pRet;
		}

		if( root->rchild != NULL )
		{
			pRightResult = getNodeByValue( root->rchild, value );
		}

		if( pRightResult != NULL ) // 找到了
		{
			pRet = pRightResult;
			return pRet;
		}
		else
		{	
			return pRet;
		}
		
		
	}

}


// 查找从根节点到pNode节点的路径
vector<Bitree> getNodePathFromRoot( Bitree root, Bitree pNode, vector<Bitree> curPath )
{
	vector<Bitree> path;

	if( NULL == root || NULL == pNode )
	{
		cout << "getNodePathFromRoot func: err -1, NULL == root || NULL == pNode" << endl;
		return path;		
	}

	if( root == pNode )
	{
		curPath.push_back( root );
		return curPath;
	}

	Bitree pleft = root->lchild;
	Bitree pright = root->rchild;
	vector<Bitree> leftResult;
	vector<Bitree> rightResult;

	curPath.push_back( root );

	if( pleft != NULL )
	{
		leftResult = getNodePathFromRoot( pleft, pNode, curPath );
	}
	
	if( pright != NULL )
	{
		rightResult = getNodePathFromRoot( pright, pNode, curPath );
	}

	if( leftResult.size() > 0 && leftResult[ leftResult.size() - 1 ] == pNode )
	{
		//cout << "find in leftTree" << endl;
		return leftResult;
	}

	if( rightResult.size() > 0 && rightResult[ rightResult.size() - 1 ] == pNode )
	{
		//cout << "find in rightTree" << endl;
		return rightResult;
	}

	return path;
}

//查找从根节点到pNode节点的路径 
//返回0表示查找成功,-1表示查找失败
int getNodePathFromRoot1( Bitree root, Bitree pNode, vector<Bitree> &path )
{
	int ret = 0; 

	if( NULL == root || NULL == pNode )
	{
		cout << "getNodePathFromRoot1 func: err -1, NULL == root || NULL == pNode" << endl;
		ret = -1;
		return ret;
	}

	if( root == pNode ) // 查找到了
	{
		path.push_back(root);
		return ret;
	}

	path.push_back(root);

	Bitree pleft = root->lchild;
	Bitree pright = root->rchild;

	int found = -1;

	if( pleft != NULL )  
	{
		int ret1 = getNodePathFromRoot1( pleft, pNode, path ); // 从左子树查找
		
		if( 0 == ret1 )
		{
			ret = ret1;
			return ret;
		}
	}

	if( pright != NULL )
	{
		int ret2 = getNodePathFromRoot1( pright, pNode, path ); // 从右子树查找
 
		if( 0 == ret2 )
		{
			ret = ret2;
			return ret;	
		}
	}

	path.pop_back(); // 左右子树都没有找到就弹出当前元素
	ret = -1;
	return ret; // 返回查找失败的标志

	
}

int main()
{
	int ret = 0;

	Bitree root = NULL;
	createBitree( &root );

	preTravel(root);
	cout << endl;

	midTravel(root);
	cout << endl;

	postTravel(root);
	cout << endl;

	cout << "============================" << endl << endl;

	int value1 = 0;
	int value2 = 0;
	Bitree pFirstNode = NULL;
/*
	while( cin >> value1 )
	{
		Bitree pNode = getNodeByValue( root, value1 );
		vector<Bitree> curPath;
		//vector<Bitree> path = getNodePathFromRoot( root, pNode, curPath );
		getNodePathFromRoot1( root, pNode, curPath );

		int len = curPath.size();
		
		for( int i = 0; i < len; ++i )
		{
			cout << curPath[i]->value << ' ';
		}
		cout << endl;
	}*/

	while( cin >> value1 >> value2 )
	{

		int status = checkValid( root, value1, value2, &pFirstNode );

		if( status < 0 )
		{
			cout << "main func: err -1, can not find " << value1 << " or " << value2 << endl;
			continue;
		}
		else if( 1 == status ) // 一个节点为另外一个节点的子节点
		{
			if( value1 == value2 )
			{

				if( root->value == value1 ) //为父亲节点
				{
					cout << "no common node with " << value1 << " and " << value2 << endl;
					continue;
				}
	
				Bitree parent = findParentOfChildByValue( root, value1 );
				
				if( parent != NULL )
				{
					cout << "common Node: " << parent->value << endl;
				}
				else
				{
					cout << "can not find common node with " << value1 << " and " << value2 << endl;
				}
				
				continue;		
			}
			else
			{
				if( root == pFirstNode )
				{
					cout << "no common node with " << value1 << " and " << value2 << endl;
					continue;
				}

				Bitree parent = findParentOfChildByPointer( root, pFirstNode );

				if( parent != NULL )
				{
					cout << "common Node: " << parent->value << endl;
				}
				else
				{
					cout << "can not find common node with " << value1 << " and " << value2 << endl;
				}

				continue;
			}
		}
		else            // status = 0
		{
			//cout << "will call findLastCommonNode" << endl;
			//cout << pFirstNode->value << endl;
			Bitree result = findLastCommonNode( root, value1, value2 );
			cout << "common Node: " << result->value << endl;
			continue;
		}
		
		
	}

	return ret;
}

/*

     10
    /  \
   5    15
  /\     /\
 3  8   12 16
/   /\  
1  6  9

./a.out 
10 5 3 1 0 0 0 8 6 0 0 9 0 0 15 12 0 0 16 0 0
10 5 3 1 8 6 9 15 12 16 
1 3 5 6 8 9 10 12 15 16 
1 3 6 9 8 5 12 16 15 10 
============================

1 3
common Node: 5
3 6
common Node: 5
3 15
common Node: 10
3 12
common Node: 10
1 16
common Node: 10
6 9
common Node: 8
3 8
common Node: 5
5 6
common Node: 10
1 2
main func: err -1, can not find 1 or 2
22 11
main func: err -1, can not find 22 or 11



*/

</span>



                    

相关文章推荐

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

从root开始遍历,如果n1和n2中的任一个和root匹配,那么root就是LCA。 如果都不匹配,则分别递归左、右子树,如果有一个 key(n1或n2)出现在左子树,并且另一个key(n1或n2)出...
  • zww0815
  • zww0815
  • 2016年04月28日 16:17
  • 247

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

/* 树中两个节点的最低公共祖先: 题型1:求二叉搜索树中两个结点的最低公共祖先 思路:如果当前值比两个结点的值都大,那么只需要向当前节点的左子树继续向下遍历即可,直到找到介于两个结点 值中间的结点。...

面试题50 树中两个节点的最低公共祖先LCA(Lowest Common Ancestor )

题目是树的最低公共祖先,我们先来考虑树是什么树? 我们从最简单的情况开始分析。 情况一:是二叉树,且是二叉搜索树(二叉排序树,二叉查找树) 分析:由于二叉排序树具有这样的特点:若它的左子树不空,则...

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

#include #include #include using namespace std; typedef struct TreeNode { int data; ...

【剑指offer】 面试题50: 树中两个结点的最低公共祖先(二叉排序数)

题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。 10 8 6 0 0 9 0 0 20 15 0 0 0 6 15 存在...

二叉树经典面试题3~树中两个结点的最低公共祖先

继续加油喽!!!

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

题目要求:求二叉树中两个节点p,q的最低公共祖先节点

剑指offer--面试题50:树中两个结点的最低公共祖先

1. 二叉排序树中求解两个结点的最低公共祖先 python实现: # Definition for a binary tree node. # class TreeNode(object): # ...

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

剑指offer 面试题50 树中两个结点的最低公共祖先 题目:给出一棵树的根结点和树中的两个结点,找到这两个结点的最低公共祖先结点。 如下面的树中,给出根结点0以及5和7两个结点,找到5、7...

【剑指offer】 面试题50: 树中两个结点的最低公共祖先

题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。 方法一: 后序遍历   基本思想: 1、两个节点不在一条线上(即两个节点不存在一个节点是另一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:面试题50:二叉树中两个节点的最低公共祖先
举报原因:
原因补充:

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