leetcode236/235.二叉树最近公共祖先总结

leetcode236.二叉树的最近公共祖先

这题是普通二叉树,我个人最开始拿到这道题的想法是联系起来以前做过的链表题,《找链表第一个相交的节点》,那道题用了个快慢指针,先求链表长度,然后快指针先走delta。


所以对于这个236题,我第一反应直观的想法是求到根节点到p、q两个节点的path,然后逆向去求两条path的第一个相交节点(或是正向求得当两个节点的值不同的时候,那么前一个节点就是最近公共祖先)

不过,这样需要额外的空间,我们可以直接在二叉树利用后序遍历的特性进行操作。
求公共祖先,如果我们能从下往上遍历就好了,但是二叉树没提供向上的指针,所以我们可以利用后序,先处理目前节点的左子树和右子树,再根据左子树和右子树的返回结果来处理当前节点

1:如果一个节点node的左子树有p or q,右子树也有p or q,那node就是他俩的最近公共祖先

2:如果一个节点node的左子树有p or q,而右子树没有p or q,那公共祖先要么在node之上,要么就是身处node的左子树的p or q本身

3:与2对称

4:如果一个节点node的左子树、右子树都没有p or q,那node为根节点的这棵子树不可能有目标公共祖先

递归法

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def post_traversal(node):
            #终止条件,空节点肯定就没找到p、q,向上返回None
            if not node:
                return None
            #遇到p or q节点,就向上返回
            if node.val == p.val or node.val == q.val:
                return node
            #后序,先处理左右孩子
            l_result = post_traversal(node.left)
            r_result = post_traversal(node.right)
            #如果左孩子、右孩子都找到了p or q,那这个node就是最近公共祖先,直接向上返回他
            #在这里要想清楚如何把这个node层层传递到最外层函数
            #这个node只能是他父节点的左孩子或者右孩子,那么对于node的父亲来说,father.left
            #或者father.right其中一个为node,另一个为None,father向上传递node,
            #然后grandfather继续传递node,一层层到最上面(这里传递逻辑还和下面几种情况相关)
            if l_result and r_result:
                return node
            #如果只有一个子树找到,另一个没找到,那就传递找到了的子树的根节点
            elif l_result and not r_result:
                return l_result
            elif not l_result and r_result:
                return r_result
            #都没找到,废了
            else:
                return None
        return post_traversal(root)

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

利用二叉搜索树的性质进行遍历就行,很简单没什么讲的

递归法:

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def recursion(node):
            if not node:
                return
            if p.val < node.val and q.val < node.val:
                result_l = recursion(node.left)
                if result_l:
                    return result_l
            if p.val > node.val and q.val > node.val:
                result_r = recursion(node.right)
                if result_r:
                    return result_r
            return node
        return recursion(root)

迭代法:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值