剑指68 最近公共祖先

本文介绍了如何利用二分查找策略在二叉搜索树中快速找到两个节点的公共祖先,同时提供了两种不同的解决方案:一种是通过层序遍历和哈希表,另一种是递归实现的前序遍历。两种方法的时间复杂度均为O(N),空间复杂度分别为O(1)和O(logN)。
摘要由CSDN通过智能技术生成

二叉搜索树的公共祖先

在这里插入图片描述
思路:搜索树一定是左<root<右,二分查找,root大于pq则pq公共祖先一定位于root左子树上,反之位于右子树,若pq在root两侧则root为公共祖先
时间复杂度O(N)空间复杂度O(1)

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

二叉树的最近公共祖先

思路1:层序遍历,构建一个hash表来存储子节点指向父节点

根据hash表找p或q回溯至root,新建一个list来存储回溯路径,然后对q回溯,并判断回溯的每一个节点是否在list内,第一个出现在list的为最近的公共祖先

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        if p==root or q==root:return root
        #hash表存节点指向
        hash={}
        que=collections.deque()
        que.append(root)
        while que:
            for _ in range(len(que)):
                i=que.popleft()
                if i.left:
                    hash[i.left]=i
                    que.append(i.left)
                if i.right:
                    hash[i.right]=i
                    que.append(i.right)
        #tem存q的回溯节点
        tem=[]
        while q!=root:
            tem.append(q)
            q=hash[q]
        #判断p的回溯路径是否在tem中
        while p!=root:
            if p in tem:return p
            p=hash[p]
        #不在,则root为公共祖先
        return root

思路2:递归

采用前序遍历,递归中止条件:
1.越过叶子节点
2.遍历至q或p节点
返回root
递归函数作用:找pq公共祖先→找root.left和root.right两颗子树的公共祖先
1.若pq不在root的左右子树中,root不是公共祖先,return
2.pq分别在左右子树中,则root必定是公共祖先,return root
3.pq都在root的左子树,返回left,继续递归,都在右子树同理

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        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)
        #pq不在root左右子树中,root不是公共祖先
        if not left and not right: return # 1.
        
        if not left: return right # 3.
        if not right: return left # 4.
        #pq
        return root # 2. if left and right:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值