Lowest Common Ancestor of a Binary Tree

在一个二叉树中指定两个节点,并在这两个节点中寻找他们的最小父节点!!!

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
struct TreeSeal
{	
	TreeSeal *left;
	TreeSeal *right;	
	TreeSeal* parent;
	TreeNode* value;
	TreeSeal():left(NULL),right(NULL),parent(0)
	{}
};
class Solution {
private:
	TreeSeal* Sroot;
public:
	//现在进行TreeNode的封装,我们可以认为使用的是适配器模式
	void InitTreePar(TreeNode* trNode,TreeSeal* sealNode){
		if(trNode==NULL)
		{
			return ;
		}
		sealNode->value=trNode;
		if(trNode->left)
		{
			//记录下左子树,并记录左子树的父节点	
			sealNode->left=new TreeSeal();
			sealNode->left->value=trNode->left;
			sealNode->left->parent=sealNode;
			InitTreePar(trNode->left,sealNode->left);
		}
		if(trNode->right)
		{
			sealNode->right=new TreeSeal();
			sealNode->right->value=trNode->left;
			sealNode->right->parent=sealNode;
			InitTreePar(trNode->right,sealNode->right);
		}
	}
	//根据给定参数p找到在TreeSeal中的相应位置,主要是TreeSeal中记录了父节点的位置
	//使用递归方式进行查找,可以认为是先序遍历方式
	void findIt(TreeNode*& p,TreeSeal*& out,TreeSeal* Sp=NULL)
	{
		if(Sp==NULL)
		{
			return ;
		}
		if(Sp->value->val==p->val)
		{
			out=Sp;
			return;
		}
		findIt(p,out,Sp->left);
		findIt(p,out,Sp->right);
	}	
	//主要是获得两个节点的共同父节点的最小值
	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {     		
		Sroot=new TreeSeal();
		//由Sroot作为根节点,进行TreeNode的封装
		InitTreePar(root,Sroot);
		TreeSeal*Sp=NULL;
		//找到节点p,在已经封装到的TreeSeal节点序列中找到对应位置
		findIt(p,Sp,Sroot);
		TreeSeal*Sq=NULL;
		//找到节点q,在已经封装到的TreeSeal节点序列中找到对应位置
		findIt(q,Sq,Sroot);
		TreeSeal* cur;
		TreeNode* result;		
		if(Sq!=NULL&&Sp!=NULL)
		{
			//如果都找到了,那么我们需要注意的是,就是这两者有木有血缘关系,						
			TreeSeal* i=Sq;
			for(;i!=NULL;i=i->parent)
			{
				if(Sp->value->val==i->value->val)
				{
					//开始查找从i之后的所有节点的最小值
					result=i->value;
					TreeSeal* j=i;
					for(;j!=NULL;j=j->parent)
					{
						if(result->val<j->value->val)
						{
							result=j->value;
						}
					}
					return result;
				}
			}
			//翻转查找					
			i=Sp;
			for(;i!=NULL;i=i->parent)
			{
				if(Sq->value->val==i->value->val)
				{
					//开始查找从i之后的所有节点的最小值
					result=i->value;
					TreeSeal* j=i;
					for(;j!=NULL;j=j->parent)
					{
						if(result->val<j->value->val)
						{
							result=j->value;
						}
					}
					return result;
				}
			}
			//不具有血缘关系.则对两个父节点序列挨个比对,得到最小值直接返回
			cur=Sq;
			result=cur->value;
			for(;cur!=NULL;cur=cur->parent)
			{
				if((cur->value->val)<(result->val))
				{
					result=cur->value;
				}
			}
			cur=Sp;
			for(;cur!=NULL;cur=cur->parent)
			{
				if(cur->value->val<result->val)
				{
					result=cur->value;
				}
			}
			return result;
		}
		else if(Sq==NULL&&Sp==NULL)
		{
			//直接返回空
			return NULL;
		}
		else
		{
			//如果有一个不为空,则直接遍历不为空的那个
			cur=((Sq==NULL)?Sp:Sq);
			result=cur->value;
			for(;cur!=NULL;cur=cur->parent)
			{
				if(cur->value->val<result->val)
				{
					result=cur->value;
				}
			}
			return result;
		}
		
	}
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值