题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 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 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
提示:
- 树中节点数目在范围
[2, 105]
内。 -109 <= Node.val <= 109
- 所有
Node.val
互不相同
。 p != q
p
和q
均存在于给定的二叉树中。
解答
- 递归遍历求解
解题思路如下:
- 首先,我们需要明确最近公共祖先的定义。在二叉树中,节点A是节点B和节点C的最近公共祖先,意味着节点A是同时包含节点B和节点C的子树中最深的节点。
- 从根节点开始遍历二叉树。如果当前节点是p或q中的一个,我们可以返回该节点,因为我们已经找到了一个目标节点。
- 递归地在左子树和右子树中寻找p和q。如果在左子树中找到了p或q的最近公共祖先,或者在右子树中找到了p或q的最近公共祖先,那么返回该节点。
- 如果左子树和右子树都没有找到p和q的最近公共祖先,那么返回根节点。
这个思路的关键在于理解最近公共祖先的定义,并通过递归的方式遍历二叉树。通过在左右子树中的递归调用,我们可以找到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) {
// 如果当前节点是p或q或者为空,直接返回该节点
if (root == nullptr || root == p || root == q) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q); // 得到root左子树拥有p或者q的最近祖先
TreeNode* right = lowestCommonAncestor(root->right, p, q); // 得到root右子树拥有p或者q的最近祖先
if (left && right) return root; // 如果左子树和右子树得到的结果都不为空,那么它们的最近公共祖先就是根节点
return left ? left : right; // 返回left和right中不为空的那个,如果都为空,那么返回哪个都一样咯
}
};