【力扣刷题】二叉搜索树的最近公共祖先

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

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

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
在这里插入图片描述

这个题如果不加上二叉搜索树难度会更大一些。但是既然给了,就应该利用左<中<右的特性。通过寻找目标点,来得到根节点到目标节点的路径。得到两个点的路径后,从路径的开始进行对比,找到最深入的一个祖先。

当然,如果不加上二叉搜索树,就可以利用后序遍历的特性来找到最近的公共祖先。

代码里,学到了新的zip函数。能够将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。 在代码中体现的是:能够在两条路径中同时同步开始搜索。如路径为(6, 2, 4, 3)与(6, 2, 0),则从6开始依次对比两个路径的点。

代码:

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        
        def getPath(root, target):
            path = []
            node = root
            while node != target:
                path.append(node)
                if target.val < node.val:
                    node = node.left
                else:
                    node = node.right
            path.append(node)  # 将target本身也加入路径中,因为有可能祖先为自身
            return path

        path_p = getPath(root, p)
        path_q = getPath(root, q)
        ancestor = None
        for u, v in zip(path_p, path_q):  # 持续向前找,找到最近的
            if u == v:
                ancestor = u  # 若找到更深入的,就更新
            else:
                break  # 跳出当前循环
        return ancestor

在这里插入图片描述


  1. 二叉树的最近公共祖先
    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
    在这里插入图片描述
    这个题就是普通的二叉树了,不能使用特性。但可以利用后序遍历的特性。后序遍历最好用迭代的,可以看这一篇。当后序遍历到目标点时,退出函数,返回栈。然后再将该目标点加入栈内,最后进行对比,找出公共祖先。
class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        def getPostOrderPath(root, target):  # 后序遍历
            stack = []
            prev = None

            while root or stack:
                while root:
                    if root != target:  # 如果不等于目标值
                        stack.append(root)  # 进栈
                        root = root.left  # 左移
                    else:  # 若等于目标值
                        return stack  # 返回栈中所有元素
                root = stack.pop()

                if root.right and root.right != prev:
                    if root != target:
                        stack.append(root)
                        root = root.right
                    else:  # 如果等于目标值
                        return stack  # 返回栈中所有元素
                else:
                    prev = root
                    root = None
        # 以上都为后序遍历的改写,下面的则与搜索二叉树的寻找代码一致
        path_p = getPostOrderPath(root, p)
        path_p.append(p)
        path_q = getPostOrderPath(root, q)
        path_q.append(q)

        ancestor = None
        for u, v in zip(path_p, path_q):
            if u == v:
                ancestor = u
            else:
                break
        return ancestor

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值