来源Leetcode
236. 二叉树的最近公共祖先
Lowest Common Ancestor of a Binary Tree
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。
题解思路
首先题目是一个二叉树问题,
关于树的问题通常可以通过递归解决。
破解问题的关键在于,两个节点的最近公共祖先,一定满足这样如下两个条件其一:
①它的左子树和右子树分别包含p和q
②它本身为p或q,且子树包含p或q
考虑为什么满足条件①的节点是答案。
若节点仅在一侧子树中包含p和q,则那一侧的字节点才可能成为答案。根节点必不是最近的祖先。
易知这样的节点只有一个,则一旦找到这样的节点,也就确定了答案。
c++代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* res;
//递归函数用于确定root中是否存在p或q
int recurve(TreeNode* root, TreeNode* p, TreeNode* q)
{
if(root == NULL)
return 0;
int middle,l,r;
l=(recurve(root->left, p, q)?1:0);//左子树包含p或q
r=recurve(root->right,p,q)?1:0;
middle=(root==p)||(root==q)?1:0;
if(l+r+middle>1)//l r m中必须满足两个
res=root; //确定答案
return l+r+middle;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
recurve(root,p,q);
return res;
}
};
这个方法虽然简单 有点难以理解。换一个简单的方法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root)
return NULL;
if(root == p || root == q)
return root;
auto left = lowestCommonAncestor(root->left, p, q);
auto right = lowestCommonAncestor(root->right, p, q);
if(!left)
return right;
if(!right)
return left;
return root; //两个都存在 一定是root
}
};
上面这个写法很好
他的本质其实是判断root树中是否存在p或q