【剑指offer】面试题68 - II. 二叉树的最近公共祖先

解题思路

方法一:参考自剑指offer
1、通过先序遍历,获取根节点到目标节点的路径
2、再通过获取的路径,求的公共节点

方法二:参考自
@yuanninesuns
思路:

1、如果p和q分别是root的左右节点,那么root就是我们要找的最近公共祖先
2、如果p和q都是root的左节点,那么返回lowestCommonAncestor(root->left, p, q)
3、如果pheq都是root的右节点,那么返回lowestCommonAncestor(root->right, p, q)
边界条件讨论:
1、如果是null表示已经找到最低了,返回null表示没找到
2、如果root与p相等或者q相等,则返回root
3、如果左子树没找到,递归函数返回null,证明p和q在root的右侧,那么最终的公共祖先就是右子树找到的结点
4、如果右子树没找到,递归函数返回null,证明p和q在root的左侧,那么最终的公共祖先就是左子树找到的结点

代码

方法一:
class Solution {
public:
	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		if (root == NULL || p == NULL || q == NULL) return NULL;
		list<TreeNode*> path1, path2;
		GetNodePath(root, p, path1);
		GetNodePath(root, q, path2);
		return GetLastCommonNode(path1, path2);
	}
	//获取从根节点到目标节点的路径
	bool GetNodePath(TreeNode* root, TreeNode* node, list<TreeNode*>& path)
	{
        //先把root节点加入到list中
		path.push_back(root);
		//找到目标节点
		if (root == node)  return true;
		//标志符found
		bool found = false;
		if (!found && root->left != NULL) found = GetNodePath(root->left, node, path);
		if (!found && root->right != NULL) found = GetNodePath(root->right, node, path);
		//如果没有找到,则返回头节点时,删除当前节点
		if (!found)
		{
			path.pop_back();
		}
		return found;
	}
	//获取共同节点
	TreeNode* GetLastCommonNode(list<TreeNode*> path1, list<TreeNode*> path2)
	{
		TreeNode* pLast = nullptr;
		list<TreeNode*>::iterator it1 = path1.begin();
		list<TreeNode*>::iterator it2 = path2.begin();
		while (it1!=path1.end()&&it2!=path2.end())
		{
			if (*it1 == *it2) pLast = *it1;
			it1++;
			it2++;
		}
		return pLast;
	}
};
方法2:
class Solution {
public:
	TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
		//如果root===NULL,则返回NULL(此处写返回root一样的);
		//如果root==p,返回p
		//如果root==q,返回q
		if (root == NULL || root == p || root == q) return root;
		//检查左子树是否含有p或q
		TreeNode* leftTree = lowestCommonAncestor(root->left, p, q);
		//检查右子树是否含有p或q
		TreeNode* rightTree = lowestCommonAncestor(root->right, p, q);
		if (leftTree == NULL) return rightTree;//左子树中没有,说明在右子树
		if (rightTree == NULL) return leftTree;//右子树中没有,说明在左子树
		//如果在root的左右子树中都找到了
		return root;
		 
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值