二叉树的最近公共祖先

155 阅读2分钟

题目

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:

image.png

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3

示例 2:

image.png

输入: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) 大小的额外空间。