在问 · 算法题解

235. 二叉搜索树的最近公共祖先

中等二叉树一次遍历找分叉点力扣原题 ↗

题目描述

输入一棵二叉搜索树的根节点 root,以及树中两个不同的节点 p 和 q。树用层序数组表示,空位记为 null;p、q 用节点值给出。

若节点 x 既是 p 的祖先,又是 q 的祖先,就称它为二者的公共祖先。一个节点也算作它自己的祖先。在所有公共祖先中,深度最大的那个就是最近公共祖先。

返回 p 和 q 的最近公共祖先。

示例 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

解释:4 位于 2 的子树中,而节点自身也算祖先,所以答案是 2。

示例 3
输入:root = [2,1], p = 2, q = 1
输出:2

解释:1 是 2 的左孩子,节点 2 自身就是最近公共祖先。

数据范围

  • 所有节点的值各不相同。
  • p != q
  • p 和 q 都在这棵树中。

解题思路:一次遍历找分叉点

利用 BST 的有序性从根往下走。如果 p、q 都比当前节点小,它们都在左子树,公共祖先也在左边;都比它大则往右。否则两者分居两侧,或者其中一个就是当前节点,当前节点就是最近公共祖先。

为什么正确

循环中 node 始终是 p 和 q 的公共祖先。

复杂度分析

时间 O(h),空间 O(1)。

易错点

判断“往左”“往右”时要用严格的小于和大于。p 或 q 等于当前节点时,当前节点就是答案,不能再往下走。这个做法只适用于 BST,普通二叉树要用 236 的递归。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        node = root
        while node:
            if p.val < node.val and q.val < node.val:
                node = node.left
            elif p.val > node.val and q.val > node.val:
                node = node.right
            else:
                return node

载入编辑器,自己跑一遍 →

其他解法

两种方法都利用了二叉搜索树的有序性,时间都是 O(h)。一次遍历把两条路径合并走,在分叉处停下,省掉了路径数组。

解法 2:两次遍历比较路径 时间 O(h),空间 O(h)

利用二叉搜索树的性质,分别从根走到 p 和 q,记录两条路径上的节点。从头同时比较两条路径,最后一个相同的节点就是最近公共祖先。

思路直观,容易说明正确性。需要存两条路径,占 O(h) 空间,还要遍历两次。

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def get_path(target):
            path = []
            node = root
            while node is not target:
                path.append(node)
                node = node.left if target.val < node.val else node.right
            path.append(node)
            return path

        pp, pq = get_path(p), get_path(q)
        ans = root
        for a, b in zip(pp, pq):
            if a is not b:
                break
            ans = a
        return ans

二叉树 专题的其他题目

查看 二叉树 全部题目 →