leetcode -- Lowest Common Ancestor of a Binary Tree -- 重点

来源:互联网 发布:北上广不相信眼泪 知乎 编辑:程序博客网 时间:2024/06/05 04:28

https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/

这里是BT不是BST,思路就是找到root到p和q的path然后找到最后的一个交点。要注意如何find Path。

如何用递归
http://bookshadow.com/weblog/2015/07/13/leetcode-lowest-common-ancestor-binary-tree/

思路1 findPath。。。用post-order

class Solution(object):    def findPath(self, root, target):        stack = []        pre = None        while stack or root:            if root:                stack.append(root)                root = root.left            else:#这里用的是post order。因为先遍历左子树,再右子树,最后再root,scan root的时候就是path                peek = stack[-1]# the first value of peek should be the most left node                if peek.right and pre != peek.right:                    root = peek.right#这里往右走,没有pop 回溯,只有在回溯的时候才需要pop                else:#一直到没有右子树,或者右子树已经遍历完了。                    if peek == target:                        return stack                    pre = stack.pop()                    root = None  #这里要记住这句话    def lowestCommonAncestor(self, root, p, q):        """        :type root: TreeNode        :type p: TreeNode        :type q: TreeNode        :rtype: TreeNode        """        path1 = self.findPath(root, p)        path2 = self.findPath(root, q)        i = 0        len1, len2 = len(path1), len(path2)        while i < min(len1, len2) and path1[i] == path2[i] :            i += 1        i -= 1        return path1[i]

这里注意不能直接用preorder 带stack的code,直接在push一个element进stack之后就判断是否为要找的node。反例[2, null, 1], 对于1来说,最后的path结果只有1.所以下面这种找path的code是不对的。要记住上面的code

        while stack or root:            if root:                stack.append(root)                if root == target:                    return stack                root = root.left            else:                root = stack.pop()                root = root.right

思路2 递归

class Solution(object):    def lowestCommonAncestor(self, root, p, q):        """        :type root: TreeNode        :type p: TreeNode        :type q: TreeNode        :rtype: TreeNode        """        #下面的if root == None return root其实就是if root  == None :return None        if root == None or root == p or root == q:            return root        # divide        left = self.lowestCommonAncestor(root.left, p, q)#返回p,q在左子树的LCA        right = self.lowestCommonAncestor(root.right, p, q)#返回p,q在右子树的LCA        # conquer # right 等于None的时候说明p和q在root.right树种没有LCA, 说明有个node不在右子树或者两个node都不在右子树。        if left and right:#两个都不为None,即在左子树有LCA,在右子树也有LCA, 那么只可能LCA 为当前的root            return root        elif left:            return left        elif right:            return right        else:            return None

自己重写findPath–postorder

    def findPath(self, root, target):        stack = []        last = None        while stack or root:            if root:                stack.append(root.val)                #last = root不用写这一句                root = root.left            else:#左节点走到了None, 然后只有两条路可以走。一条就是递归stack[-1]的右子树,另一条就是回溯                peek = stack[-1]                if peek.right and last != peek.right:#第一条路,要先往右子树scan。不要先想到if last == peek.right                    root = root.right                else:#第二条路,回溯,访问这个节点,更新last                    if peek == target:                        return stack                    last = stack.pop()#回溯的时候写记录last就行。                    root = None#记得写。因为在更新last的时候,用的是stack pop,会stack会缩短一个node,所以要继续回溯访问stack[-1],所以要走到回溯的点的else
0 0
原创粉丝点击