题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 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
题解
一、终止条件
1.当越过叶子节点,直接返回 null;
2.当 root 等于 p、q 时,直接返回 root
二、递归工作
1.开始递归左子节点,返回值为left;
2.开始递归右子节点,返回值为right;
三、返回值
1.当 left、right 同时为空时,说明左、右子树中都不包含 p、q,返回 null;
2.当 left、right 同时不为空时,说明 p、q 分别在root的异侧,因此 root 为最近公共祖先,返回 root;
3.当 left 为空,right 不为空时,说明 p、q 都不在 root 的左子树中,直接返回 right;
4.当 right 为空,left 不为空时,与 3 同理;
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
// root 为 null 或者找到对应节点
if (!root || root === p || root === q) {
return root;
}
// 递归查找左子树
const left = lowestCommonAncestor(root.left, p, q);
// 递归查找右子树
const right = lowestCommonAncestor(root.right, p, q);
// 公共节点不在左侧子树中,返回右侧子树结果
if (!left) {
return right;
}
// 公共节点不在右侧子树中,返回左侧子树结果
if (!right) {
return left;
}
// 不在子树中,返回根节点
return root;
};
时间复杂度O(N) : 其中 N 为二叉树节点数;最差情况下,需要递归遍历树的所有节点。
空间复杂度O(N) : 最差情况下,递归深度达到 N ,系统使用 O(N) 大小的额外空间。