算法题分享 | 二叉搜索树的最近公共祖先

24 阅读2分钟

iPad壁纸🗓文字篇19_9_舞木子_来自小红书网页版.jpg

题目

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

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

例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

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

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

题解

解题思路

可以分别在树中查找 p 和 q 结点,并且分别使用数组 A、B 记录查找中经过的每个节点,最终两个数组中最后一个相等的元素即为 p 和 q 的最近公共祖先。

但是这种方式需要查找两次,是否可以仅使用一次的查找解决呢?
实际上是可以的。

我们可以同时结合 p 和 q 进行处理。在遍历时,对于每个结点 node,一共有三种情况:

  1. p 和 q 的值均小于 node.val,说明两者都在 node 的左子树中,当前还没分岔,下一步查找左子树;
  2. p 和 q 的值均大于 node.val,说明两者都在 node 的右子树中,当前还没分岔,下一步查找右子树;
  3. 前两种情况均不满足,说明两者要么就是分别在 node 的左右子树,要么其中之一就是 node 本身,无论如何,node 都是我们要找的最近公共祖先,直接返回 node 即可。

代码

/**
 * Definition for a binary tree node.
 * public 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) {
            return null;
        }

        TreeNode node = root;

        while (true) {

            if (p.val < node.val && q.val < node.val) {
                node = node.left;
            } else if (p.val > node.val && q.val > node.val) {
                node = node.right;
            } else {
                return node;
            }
        }
    }
}

复杂度分析

  • 时间复杂度:O(n)
    n 是树的结点数。
  • 空间复杂度:O(1)

优质项目推荐

推荐一个可用于练手、毕业设计参考、增加简历亮点的项目。

lemon-puls/txing-oj-backend: Txing 在线编程学习平台,集在线做题、编程竞赛、即时通讯、文章创作、视频教程、技术论坛为一体

公众号

有兴趣可以关注公众号一起学习更多的干货哈!

扫码_搜索联合传播样式-白色版.png