面试题 04.08. 首个共同祖先

题目

设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点存储在另外的数据结构中。注意:这不一定是二叉搜索树。

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

 	3
   / \
  5   1
 / \ / \
6  2 0  8
  / \
 7   4

示例1:

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

示例2:

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

分析: 找到两个节点的首个公共祖先点,分两种情况,第一种:该祖先点不等于其中任何一个节点,那么两个节点必然分别位于左右子树之中,第二种:该祖先点为其中一个节点,那么另外一个节点必然位于左子树或者右子树之中, 采用后续遍历的方法自底向上查找,先找到其中一个节点,做好标记,当继续查找的节点满足上述两个条件之一,则该节点为最近公共祖先节点

方法1: 后序遍历递归查找

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        find_p = None
        def LRD(root, p, q, find_p):
            if root == None:
                return False, find_p
            lfind, find_p = LRD(root.left, p, q, find_p)
            rfind, find_p = LRD(root.right, p, q, find_p)
            # print(root)
            # print(lfind)
            # print(rfind)
            if lfind and rfind or ((root == p or root == q) and (lfind or rfind)):
                find_p = root
            return root == p or root == q or lfind or rfind, find_p
        _, find_p = LRD(root, p, q, find_p)
        return find_p

方法2: 采用额外的字典记录每一个节点及其父节点的对应关系,然后我们就可以利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访问过的节点,再从 q 节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的首个共同祖先。

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        map_dict = {}
        map_dict[root.val] = None
        def dfs(root):
            if root == None:
                return None
            left = root.left
            right = root.right
            left_val = dfs(left)
            right_val = dfs(right)
            if left_val != None:
                map_dict[left_val]  = root
            if right_val != None:
                map_dict[right_val] = root
            return root.val
        dfs(root)
        p_list = []
        p_list.append(p)
        while p != None:
            p_list.append(map_dict[p.val])
            p = map_dict[p.val]
        # print(p_list)
        while q != None:
            if q in p_list:
                return q
            q = map_dict[q.val]
        return None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值