秋招-算法-二叉树的最近公共祖先

50 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情 >>

一、题目描述 LeetCode-236

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

image.png

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

示例:

image.png

输入: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节点的左右子树中,则最近公共祖先为root,直接返回;
  2. root = p,且节点q在root的左子树或右子树中,则返回节点p;
  3. root = q,且节点p在root的左子树或右子树中,则返回节点q;

在编写代码时考虑二叉树递归遍历方法,当遍历遇到p或q节点时返回。在进行返回时也分为几种情况:

  1. if (left != null && right != null) return root;
  2. if (left == null) return right;
  3. if (right == null) return left;
  4. if (left == null && right == null) return null;

三、代码

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution{
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || p == root || q == root) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if (left == null && right == null){
            return null;
        }
        if (left == null) {
            return right;
        }
        if (right == null) {
            return left;
        }
        return root;
    }
}

四、总结

本题巧妙的利用二叉树回溯的思想,对左右子树进行判断并层层返回,最后得到p,q的最近公共祖先,时间复杂度和空间复杂度均为O(N),其中N为二叉树的节点树。