给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点5和节点1的最近公共祖先是节点3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点5和节点4的最近公共祖先是节点5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉树中。
思路: 采用先序遍历回溯方法
1、最近公共祖先有三种情况:p,q在root的两侧;root=p,q在root左(右)子树中;root=q,p在root左(右)子树中。
2、递归左子树、右子树。
递归终止条件 当root为null或root等于q或root等于p,返回root。 递归开始 先递归左子树,返回值记为left。
再递归右子树,返回值记为right。
返回值 1、当left和right都为空时,即root的左(右)子树中都不含有p、q,直接返回null。
2、当left和right都不为空时,即p、q在root的左右子树中,root为最近公共祖先,返回root。
3、当left为空,right不为空时,有两种情况
a、p 、 q 其中一个在 root 的右子树中,此时right指向p或q;
b、p 、q 两节点都在 root 的右子树中,此时的right指向最近公共祖先节点 ;返回right。
4、当right为空,left不为空时,与3同理,返回left。
代码实现:
/**
* 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* left = lowestCommonAncestor(root->left, p, q); //递归左子树
TreeNode* right = lowestCommonAncestor(root->right, p, q); //递归右子树
if(left == NULL)
return right;
if(right == NULL)
return left;
return root; //left和right都不为空,则root即为最近公共祖先
}
};