Leetcode 1123:最深叶节点的最近公共祖先(超详细的解法!!!)

给你一个有根节点的二叉树,找到它最深的叶节点的最近公共祖先。

回想一下:

  • 叶节点 是二叉树中没有子节点的节点
  • 树的根节点的 深度0,如果某一节点的深度为 d,那它的子节点的深度就是 d+1
  • 如果我们假定 A 是一组节点 S最近公共祖先S 中的每个节点都在以 A 为根节点的子树中,且 A 的深度达到此条件下可能的最大值。

示例 1:

输入:root = [1,2,3]
输出:[1,2,3]

示例 2:

输入:root = [1,2,3,4]
输出:[4]

示例 3:

输入:root = [1,2,3,4,5]
输出:[2,4,5]

提示:

  • 给你的树中将有 1 到 1000 个节点。
  • 树中每个节点的值都在 1 到 1000 之间。

解题思路

首先不难想到暴力法,也就是先找到最深的叶子节点,然后再找到叶子节点的公共祖先。如果找到最深的叶子节点?如何找公共祖先?这实际上是leetcode之前的几个问题

Leetcode 102:二叉树的层次遍历(最详细解决方案!!!)

Leetcode 236:二叉搜索树中第K小的元素(最详细的解法!!!)

我们知道叶子节点的个数可能是一个,也可能是许多个。那么一个叶子节点的话,我们直接返回那个叶子节点即可。如果有许多个怎么办?我们只需返回最左边和最右边叶子节点的最近公共祖先即可。接下来就是复制代码了

class Solution:
    def lcaDeepestLeaves(self, root: TreeNode) -> TreeNode:
        le = self.levelOrder(root)
        if len(le[-1]) == 1:
            return le[-1][0]
        return self.lowestCommonAncestor(root, le[-1][0], le[-1][-1])

    def levelOrder(self, root):
        ret = list()
        if not root:
            return ret

        from queue import Queue
        q = Queue()
        q.put((root, 0))
        while not q.empty():
            node, level = q.get()
            if level == len(ret):
                ret.append([])
                
            ret[level].append(node)
            if node.left != None:
                q.put((node.left, level + 1))
            if node.right != None:
                q.put((node.right, level + 1))

        return ret

    def lowestCommonAncestor(self, root, p, q):
        if not root or root == p or root == q: 
            return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if left and right:
            return root
        return left if left else right

上面的代码是可以通过的,但是非常的臃肿。我们一直说对于树型问题首先考虑递归,那么这个问题怎么通过递归来做呢?通过前序遍历访问整颗二叉树,每次返回当前整个树的叶子节点的最大深度d叶子节点的最近公共祖先x

我们先递归求解出左子树的ldlx和右子树的rdrx(分别对应最大深度和最近公共祖先)。那么当ld < rd的时候,此时树的最大深度就是rd+1,此时的最深叶节点的最近公共祖先自然就是rx。当ld > rd的时候,此时树的最大深度就是ld+1,此时的最深叶节点的最近公共祖先自然就是lx。当ld == rd的时候,此时树的最大深度就是ld+1或者rd+1,此时的最深叶节点的最近公共祖先自然就是root

最后思考边界情况,也就是当root==None的时候,此时的深度就是0,公共祖先就是None

class Solution:
    def lcaDeepestLeaves(self, root: TreeNode) -> TreeNode:
        def dfs(root):
            if not root:
                return 0, None
            l, r = dfs(root.left), dfs(root.right)
            if l[0] < r[0]:
                return r[0] + 1, r[1]
            elif l[0] > r[0]:
                return l[0] + 1, l[1]
            else:
                return l[0] + 1, root
            
        return dfs(root)[1]

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页