题目:236.二叉树的最近公共祖先. - 力扣(LeetCode)
题解:对于最近公共祖先问题,由于本题特定从顶向下,那么需要思考祖先的位置。
显然根是所有节点的祖先,那么根节点必定为公共祖先。如何确定该节点是否为最近公共祖先呢?
事实上,如果根不是最近公共祖先,那么剩余两个点,一定在根的左子树,或者根的右子树里。
举例如图:
对于节点P = 4, Q = 6而言,最近公共祖先为1
对于节点P = 4, Q = 5而言,最近公共祖先为2
于是我们可以参考递归思想,对于每个点,递归左右子树。
如果递归左子树的过程,没有找到P点或者Q点,那么最近公共祖先可以更新为右子树的根节点;
如果递归右子树的过程,没有找到P点或者Q点,那么最近公共祖先可以更新为左子树的根节点;
如果两边都找到了,那么当前的根节点即为公共祖先。
对递归不熟悉可以监看下述举例:
/**
* 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 == NULL || root == p || root == q)
{
return root;
}
TreeNode* pp = lowestCommonAncestor(root->left, p, q);
TreeNode* qq = lowestCommonAncestor(root->right, p, q);
if(pp == NULL) return qq;
if(qq == NULL) return pp;
return root;
}
};
递归过程,我们以P = 2, Q = 6为例:
1. 执行第一层TreeNode* pp = lowestCommonAncestor(root->left, p, q);
2. 递归第一层PP所在子树, root = p = 2(节点) 返回root = 2(节点),到此第一层左子树递归结束。
3. 执行第一层TreeNode* qq = lowestCommonAncestor(root->right, p, q);
4. 递归第一层QQ所在子树,root = p = 3(节点),不等于Q = 6(节点),执行当root = 3时,第二层TreeNode* pp = lowestCommonAncestor(root->left, p, q);
5. 递归第二层PP所在子树, root = p = NULL(节点) 返回root = NULL(节点),到此第二层左子树递归结束。
6. 执行root = 3,第二层TreeNode* qq = lowestCommonAncestor(root->right, p, q);
7. 递归第二层QQ所在子树,root = p = 6(节点),等于Q = 6(节点),返回到第二层,此时PP = NULL, QQ = 6(节点)。
8. 因为第二层的左子树PP = NULL,因此返回公共节点root = 3.
9. 至此,第一层递归完毕,左右子树执行最后一个代码,返回公共节点root = 1
其余样例自行模拟,不再解释,受限于时间,在此不做动画。