Leetcode刷题笔记-Tree

本文深入探讨了LeetCode上关于树的算法题解,包括树的遍历、层次遍历、最大路径和等核心概念,并提供了实际代码实现。重点介绍了不同遍历方式如中序、先序和后序遍历的原理与应用,以及如何利用这些遍历方法解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Background:

Tree Traversals (Inorder, Preorder and Postorder) - GeeksforGeeks

Unlike linear data structures (Array, Linked List, Queues, Stacks, etc) which have only one logical way to traverse them, trees can be traversed in different ways. Following are the generally used ways for traversing trees.

Example Tree

Depth First Traversals:
(a) Inorder (Left, Root, Right) : 4 2 5 1 3
(b) Preorder (Root, Left, Right) : 1 2 4 5 3
(c) Postorder (Left, Right, Root) : 4 5 2 3 1

Breadth First or Level Order Traversal : 1 2 3 4 5
Please see this post for Breadth First Traversal.

Inorder Traversal (Practice):中序

Algorithm Inorder(tree)
   1. Traverse the left subtree, i.e., call Inorder(left-subtree)
   2. Visit the root.
   3. Traverse the right subtree, i.e., call Inorder(right-subtree)

Uses of Inorder
In case of binary search trees (BST), Inorder traversal gives nodes in non-decreasing order. To get nodes of BST in non-increasing order, a variation of Inorder traversal where Inorder traversal s reversed can be used.
Example: Inorder traversal for the above-given figure is 4 2 5 1 3.


Preorder Traversal (Practice):前序

Algorithm Preorder(tree)
   1. Visit the root.
   2. Traverse the left subtree, i.e., call Preorder(left-subtree)
   3. Traverse the right subtree, i.e., call Preorder(right-subtree) 

Uses of Preorder
Preorder traversal is used to create a copy of the tree. Preorder traversal is also used to get prefix expression on of an expression tree. Please see http://en.wikipedia.org/wiki/Polish_notation to know why prefix expressions are useful.
Example: Preorder traversal for the above given figure is 1 2 4 5 3.


Postorder Traversal (Practice):后序

Algorithm Postorder(tree)
   1. Traverse the left subtree, i.e., call Postorder(left-subtree)
   2. Traverse the right subtree, i.e., call Postorder(right-subtree)
   3. Visit the root.

Uses of Postorder
Postorder traversal is used to delete the tree. Please see the question for deletion of tree for details. Postorder traversal is also useful to get the postfix expression of an expression tree. Please see http://en.wikipedia.org/wiki/Reverse_Polish_notation to for the usage of postfix expression.


 ==============================

1080. Insufficient Nodes in Root to Leaf Paths

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sufficientSubset(self, root: Optional[TreeNode], limit: int) -> Optional[TreeNode]:
        # 自己写的,题目的意思是,如果通过该点的所有从root到leaf的路径上的sum全部都小于limit 那么就删除
        # 该点
        def isSufficient(node, total):
            # 到最leaf的节点再判断sum是不是小于limit 再把这个ture/false网上传
            if not node.left and not node.right: 
                total += node.val
                if total < limit:
                    return False
                else:
                    return True

            total += node.val
            left_re = right_re = False
            if node.left:
                left_re = isSufficient(node.left, total)
            if node.right:
                right_re = isSufficient(node.right, total)

            if not left_re:
                node.left = None
            if not right_re:
                node.right = None
                
            return left_re or right_re
        
        return root if isSufficient(root, 0) else None # root可能也是非法的

331. Verify Preorder Serialization of a Binary Tree

class Solution(object):
    def isValidSerialization(self, preorder):
        """
        We just need to remember how many empty slots we have during the process.

        Initially we have one ( for the root ).

        for each node we check if we still have empty slots to put it in.

        a null node occupies one slot.
        a non-null node occupies one slot before he creates two more. the net gain is one.

        """
    
        
        p = preorder.split(',')
        
        #initially we have one empty slot to put the root in it
        slot = 1
        for node in p:
            
            # no empty slot to put the current node
            if slot == 0:
                return False
                
            # a null node?
            if node == '#':
                # ocuppy slot
                slot -= 1
            else:
                # create new slot
                slot += 1
        
        #we don't allow empty slots at the end
        return slot==0


1026. Maximum Difference Between Node and Ancestor

class Solution:
    def maxAncestorDiff(self, root: Optional[TreeNode]) -> int:
        # find bigest and smallest values from left and right
        self.re = 0
        def dfs(node):
            if not node:
                return None, None
            lmin, lmax = dfs(node.left)
            rmin, rmax = dfs(node.right)
            cur = node.val
            l = r = cur
            for v in (lmin, lmax, rmin, rmax):
                if v != None:
                    self.re = max(self.re, abs(cur - v))
                    l = min(l, v)
                    r = max(r, v)
            return l, r
        dfs(root)
        return self.re

1325. Delete Leaves With a Given Value

class Solution:
    def removeLeafNodes(self, root: Optional[TreeNode], target: int):
        # O(N) solution with DFS
        def dfs(node):
            if not node:
                return None
            
            if node.val == target and not node.left and not node.right:
                return None
            
            node.left = dfs(node.left)
            node.right = dfs(node.right)

            if node.val == target and not node.left and not node.right:
                return None
            return node
        
        return dfs(root)

    # 下面是自己写的

    #     root, _ = self.remove(root, target)
    #     return root

    # def remove(self, root: Optional[TreeNode], target: int):
    #     left, right = None, None
    #     if root.left:
    #         left, shouldDel = self.remove(root.left, target)
    #         if shouldDel:
    #             root.left = None
    #     if root.right:
    #         right, shouldDel = self.remove(root.right, target)
    #         if shouldDel:
    #             root.right = None

    #     if left == right == None and root.val == target:
    #         return None, True
    #     return root, False

894. All Possible Full Binary Trees

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:
        
        if not n or not n % 2:  # 如果是偶数个的就没必要继续了,因为不会是full binrary tree
            return []
        
        if n == 1:
            return [TreeNode()]
        
        res = []
        for i in range(1, n-1, 2):  # 奇数
            lefts = self.allPossibleFBT(i)
            rights = self.allPossibleFBT(n-1-i)
            for left in lefts:
                for right in rights:
                    root = TreeNode(0, left, right)
                    res.append(root)
        return res

814. Binary Tree Pruning

class Solution:
    def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        # Bottom up
        def dfs(node):
            if not node:
                return 0  # 0 means this node can be deleted 

            left = dfs(node.left)
            right = dfs(node.right)
            if left == 0:
                node.left = None  # delete the node
            if right == 0:
                node.right = None  # delete the node

            if left == right == node.val == 0:  # left and right can be deleted and cur node.val = 0 means it can be deleted 
                return 0
            
            return 1  # cannot be deleted 
    
        
        return None if dfs(root) == 0 else root  # edge case to delete root
    # 答案的写法:
    '''
    if not root: return None
    root.left = self.pruneTree(root.left)
    root.right = self.pruneTree(root.right)
    if not root.left and not root.right and not root.val: return None
    return root
    '''

1650. Lowest Common Ancestor of a Binary Tree III

  

class Solution:
    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
        # 类似于 linkedlist 快慢指针
        '''
        For anyone struggling to see it, imagine to nodes, p and q, whose paths merge and become common after a certain number of steps.
        p1 -> p2 -> p3 -> c1 -> c2 -> c3
        q1 -> q2 -> q3 -> c1 -> c2 -> c3
        If the distance from p1 to c1 is the same as the distance from q1 to c1, it's pretty obvious this algorithm will find when c1 == c1.

        But now imagine those distances are different.
        p1 -> p2 -> p3 -> c1 -> c2 -> c3
        .........................q1 -> c1 -> c2 -> c3

        If you force them to switch paths after they reach c3:
        P Travels: (3 steps to c1), (3 common steps to q1), (1 step to c1)
        Q Travels: (1 step to c1), (3 common steps to p1), (3 steps to c1)

        OR put another way

        P Travels: PC, C, QC
        Q Travels: QC, C, PC

        where C is the common paths. PC is p's unique path to the common ancestor. QC is q's unique path.
        '''
        p1, p2 = p, q
        
        while p1 != p2:
            p1 = p1.parent if p1.parent else q
            p2 = p2.parent if p2.parent else p
        
        return p1

1373. Maximum Sum BST in Binary Tree

class Solution:
    def maxSumBST(self, root: Optional[TreeNode]) -> int:
        # 不同于 https://leetcode.com/problems/validate-binary-search-tree/ 两个largerThan, smallThan 是从上传到下面, 这题需要这2个值从下往上传
        # O(n) Time complexity 
        self.re = 0
        
        def isValidBST(node):
            if not node:
                return True, 0, float('inf'), float('-inf')   # isBST, sum of BST, minVal in BST, maxVal in BST, 后面这两个float 是根据line 20写出来的
            
            left, sum_left, minLV, maxLV = isValidBST(node.left)
            right, sum_right, minRV, maxRV = isValidBST(node.right)
            
            if left and right and node.val > maxLV and node.val < minRV:
                total = node.val + sum_left + sum_right
                self.re = max(self.re, total)
                return True, total, min(node.val, minLV), max(maxRV, node.val) 
            
            return False, 0, -1, -1  # when false, we don't care the max_val, min_val
        
        isValidBST(root)
        return self.re

968. Binary Tree Cameras

class Solution:
    def minCameraCover(self, root: Optional[TreeNode]) -> int:
        # 从叶子节点开始向上
        # 空节点返回-1 表示没有,也不需要被上层cover
        # 返回0 表示当前没有, 需要被cover
        # 返回1, 表示当前有, 可以cover上面 (子节点有一个一定需要被cover)
        # 返回-1 表示当前没有,也不需要被上面cover  # 这个可以直接返回-1
        
        self.res = 0
        
        def dfs(node):
            if not node:  # 空节点, 
                return -1
            l, r = dfs(node.left), dfs(node.right)
               
            if 0 in [l, r]:  # 子节点有一个需要被cover
                self.res += 1
                return 1
            
            if l == 1 or r == 1:  # 当前没有,也不需要被cover
                return -1
            
            return 0
            
        dfs(root)
        return self.res + (dfs(root) == 0)  # edge case: root 节点的左右两边都是空的, 也不需要被cover, 这时候root节点还是需要有个摄像头

95. Unique Binary Search Trees II

class Solution(object):
    def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        def generate_trees(start, end):
            if start > end:
                return [None]
            
            allTrees = []
            for i in xrange(start, end+1):            # pick an element as root between start to end
                leftTrees = generate_trees(start, i-1)
                rightTrees = generate_trees(i+1, end)
                
                # combine left root right
                for left in leftTrees:
                    for right in rightTrees:
                        root = TreeNode(i)  # 这个不能写在上面
                        root.left = left
                        root.right = right
                        allTrees.append(root)
            return allTrees
        
        return generate_trees(1, n) if n else []

617. Merge Two Binary Trees

class Solution(object):
    def mergeTrees(self, t1, t2):
        if not t1 and not t2: return None
        res = TreeNode(0)
        res.val = (t1.val if t1 else 0) + (t2.val if t2 else 0)
        res.left = self.mergeTrees(t1 and t1.left, t2 and t2.left)
        res.right = self.mergeTrees(t1 and t1.right, t2 and t2.right)
        return res

103. Binary Tree Zigzag Level Order Traversal

class Solution(object):
    def zigzagLevelOrder(self, root):
        if not root: return []
        level = [root]
        re = []
        flag = 1
        while level:
            Next = []
            temp = []
            while level:
                node = level.pop(0)
                temp.append(node.val)
                if node.left: Next.append(node.left)
                if node.right: Next.append(node.right)
            level = Next
            re.append(temp[::flag])
            flag *= -1
        return re

437. Path Sum III

class Solution(object):
    def pathSum(self, root, sum):
        if not root: return 0
        return self.getSumFrom(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum)
    
    def getSumFrom(self, node, s):
        if not node:
            return 0
        cur = 0
        if node.val == s:
            cur += 1
        return cur + self.getSumFrom(node.left, s-node.val) + self.getSumFrom(node.right, s-node.val)

222. Count Complete Tree Nodes

it needs to find the depth for its left and right child, which is log(n), and then it needs to run countNodes for its left child or right child which is another log(n), so it's log(n) * log(n).

class Solution(object):
    def countNodes(self, root):
        if not root: return 0
        
        leftDepth = self.getDepth(root.left)
        rightDepth = self.getDepth(root.right)
        
        if leftDepth == rightDepth:  # left is full binary tree
            return 2**leftDepth + self.countNodes(root.right)
        else:
            # leftDepth > rightDepth right is a full binary tree
            return 2**rightDepth + self.countNodes(root.left)
        
    def getDepth(self, node):
        if not node: return 0
        return self.getDepth(node.left) + 1

333. Largest BST Subtree

class Solution(object):
    def largestBSTSubtree(self, root):
        self.re = 0
        def find(node):
            if not node: return float('inf'), float('-inf'), 0
            lmin, lmax, lnum = find(node.left)
            rmin, rmax, rnum = find(node.right)
            n = float('-inf')
            if node.val > lmax and node.val < rmin:
                n = lnum + rnum + 1
                self.re = max(n, self.re)
            return min(node.val, lmin), max(node.val, rmax), n
        find(root)
        return self.re

450. Delete Node in a BST

class Solution(object):
    def deleteNode(self, root, key):
        if not root: return None
        if key > root.val:
            root.right = self.deleteNode(root.right, key)
        elif key < root.val:
            root.left = self.deleteNode(root.left, key)
        else:
            if not root.left:
                return root.right
            if not root.right:
                return root.left
            
            right = root.right
            left = root.left
            temp = right
            while temp.left:
                temp = temp.left
            temp.left = left
            root = right
        return root

655. Print Binary Tree

class Solution(object):
    def printTree(self, root):
        def height(root):
            if not root: return 0
            left = height(root.left)
            right = height(root.right)
            return max(left, right) + 1
        
        high = height(root)
        width = 2**high - 1
        res = [[''] *width for _ in xrange(high)]
        def update(i, j, level, node, res):
            if not node: return
            mid = (i+j) / 2
            res[level][mid] = str(node.val)
            update(i, mid-1, level+1, node.left, res)
            update(mid+1, j, level+1, node.right, res)
        update(0, width-1, 0, root, res)
        return res

979. Distribute Coins in Binary Tree

子节点需要几个,和子节点多出几个,加起来。 

class Solution(object):
    res = 0
    def distributeCoins(self, root):
        def dfs(node):
            if not node: return 0
            left = dfs(node.left)
            right = dfs(node.right)
            self.res += abs(left) + abs(right)  # 这里有绝对值
            return node.val + left + right - 1
        dfs(root)
        return self.res

662. Maximum Width of Binary Tree

If the index of a node is i, the indices of its two children are 2*i and 2*i + 1.  

class Solution(object):
    def widthOfBinaryTree(self, root):

        if not root: return 0
        level = [(root, 1)]
        w = 1
        while level:
            next = []
            for node, ids in level:
                if node.left: next.append((node.left, ids*2))
                if node.right: next.append((node.right, ids*2+1))
            w = max(w, level[-1][1]-level[0][1]+1)
            level = next
        return w

366. Find Leaves of Binary Tree

class Solution(object):
    def findLeaves(self, root):
        d = collections.defaultdict(list)
        
        def height(node):
            if not node: return -1
            left = height(node.left)
            right = height(node.right)
            h = max(left, right) + 1
            d[h].append(node.val)
            return h
        
        high = height(root)
        res = []
        for i in xrange(high+1):
            res.append(d[i])
        return res

865. Smallest Subtree with all the Deepest Nodes

class Solution(object):
    def subtreeWithAllDeepest(self, root):
        # one pass
        def deep(root):
            if not root: return None, 0
            left, ldeep = deep(root.left)
            right, rdeep = deep(root.right)
            if ldeep > rdeep:
                return left, ldeep + 1
            elif ldeep < rdeep:
                return right, rdeep + 1
            else:
                return root, ldeep+1        
        return deep(root)[0]

958. Check Completeness of a Binary Tree

新的level by level的方法,用i来控制,就不需要nextLevel了 

 class Solution(object):
    def isCompleteTree(self, root):
        level = [root]
        i = 0
        while level[i]:
            node = level[i]
            level.append(node.left)
            level.append(node.right)
            i += 1
        return not any(level[i:])

536. Construct Binary Tree from String

class Solution(object):
    def str2tree(self, s):
        
        left = s.find('(')  # 第一个左括号的Idx
        if left < 0:
            return TreeNode(int(s)) if s else None
        
        p = 0
        for i, c in enumerate(s):
            if c == '(': p += 1
            elif c == ')': p -= 1
            if p == 0 and i > left: break
                
        root = TreeNode(int(s[:left]))
        root.left = self.str2tree(s[left+1:i])
        root.right = self.str2tree(s[i+2:-1])  # 注意这里+2, 和-1 最后一个)是不要的
        return root

617. Merge Two Binary Trees

class Solution(object):
    def mergeTrees(self, t1, t2):
        if t1 and t2:
            root = TreeNode(t1.val+t2.val)
            root.left = self.mergeTrees(t1.left, t2.left)
            root.right = self.mergeTrees(t1.right, t2.right)
            return root
        else:
            return t1 or t2
       

545. Boundary of Binary Tree

class Solution(object):
    def boundaryOfBinaryTree(self, root):
        def dfs_leftmost(node):  # preorder
            if not node or not node.left and not node.right:
                return
            re.append(node.val)
            if node.left:
                dfs_leftmost(node.left)
            else:
                dfs_leftmost(node.right)
                
        def dfs_leaves(node):  # inorder
            if not node:
                return
            dfs_leaves(node.left)
            if node != root and not node.left and not node.right:
                re.append(node.val)
            dfs_leaves(node.right)
        
        def dfs_rightmost(node):  # postorder
            if not node or not node.left and not node.right:
                return
            if node.right:
                dfs_rightmost(node.right)
            else:
                dfs_rightmost(node.left)
            re.append(node.val)

        if not root:
            return []
        re = [root.val]
        dfs_leftmost(root.left)
        dfs_leaves(root)
        dfs_rightmost(root.right)
        return re
    

235. Lowest Common Ancestor of a Binary Search Tree

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        while root:
            if root.val > p.val and root.val > q.val:
                root = root.left
            elif root.val < p.val and root.val < q.val:
                root = root.right
            else:
                return root

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

For example, given

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if inorder:
            ind = inorder.index(preorder.pop(0))
            root = TreeNode(inorder[ind])
            root.left = self.buildTree(preorder, inorder[0: ind])
            root.right = self.buildTree(preorder, inorder[ind+1:])
            return root

106. Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

For example, given

inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7
class Solution(object):
    def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        if not postorder or not inorder:
            return
        
        root = TreeNode(postorder.pop())
        inorderIndex = inorder.index(root.val)
        
        root.right = self.buildTree(inorder[inorderIndex+1:], postorder)
        root.left = self.buildTree(inorder[:inorderIndex], postorder)
        
        return root

230. Kth Smallest Element in a BST

 递归访问左节点->自己->右节点


class Solution(object):
    def kthSmallest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        self.count = self.result = 0
        self.helper(root, k)
        return self.result
    
    def helper(self, root, k):
        if not root:
            return  
        
        self.helper(root.left, k)
        self.count += 1
        
        if self.count == k:
            self.result = root.val
            return
        
        self.helper(root.right, k)

94. Binary Tree Inorder Traversal

inorder preorder的可以整理一下

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root is None:
            return []
        
        return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)

236. Lowest Common Ancestor of a Binary Tree

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        stack = [root]
        parent = {root: None}

        while p not in parent or q not in parent:
            node = stack.pop()
            if node.left:
                parent[node.left] = node
                stack.append(node.left)
            if node.right:
                parent[node.right] = node
                stack.append(node.right)
            
        ancestors = set()
        while p:
            ancestors.add(p)
            p = parent[p]
        
        while q not in ancestors:
            q = parent[q]
            
        return q
        

1644. Lowest Common Ancestor of a Binary Tree II

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        '''
         different with 236. Last Common Ancestor of Binary Tree, p q 是有可能不存在的,所以不能找到p或者q的时候就返回了,而是要继续遍历整颗树
        '''
        self.p = False  # find p? 
        self.q = False  # find q?
            
        def lca(node, p, q):
            if not node:
                return None
            left = lca(node.left, p, q)  # 这两个left right会保证一直dfs 进去
            right = lca(node.right, p, q)
            if node == p:
                self.p = True
                return node
            if node == q:
                self.q = True
                return node
            
            if left and right:
                return node
            
            return left or right
        
        node = lca(root, p, q)
        return node if self.p and self.q else None

102. Binary Tree Level Order Traversal

medium但是太多同类型的了所以很简单

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
         
        q = [root] if root else []
        re = []
        while q:
            cur = [node.val for node in q]
            re.append(cur)
            q = [n for node in q for n in (node.left, node.right) if n]
        
        return re

297. Serialize and Deserialize Binary Tree

449. Serialize and Deserialize BST

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Codec:

    def serialize(self, root):
        if not root: return '#'

        preorder = str(root.val)
        left = self.serialize(root.left)
        right = self.serialize(root.right)
        return ".".join([preorder, left, right])
        

    def deserialize(self, data):
        # print(data)
        nodes = data.split(".")
        self.i = 0
        def dfs():
            if self.i == len(nodes):
                return None
            v = nodes[self.i]
            self.i += 1
            if v == '#':
                return None
            
            root = TreeNode(int(v))
            root.left = dfs()
            root.right = dfs()
            return root
        return dfs()

428. Serialize and Deserialize N-ary Tree

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        if children is None:
            children = []
        self.val = val
        self.children = children
"""

class Codec:
    def serialize(self, root: 'Node') -> str:
        s = []

        def preorder(node):
            if not node:
                return
            
            s.append(str(node.val))

            for child in node.children:
                preorder(child)

            s.append('#')  # indicates no more child
        preorder(root)
        # 每个字符都是用.链接起来
        return ".".join(s)
        
	
    def deserialize(self, data: str) -> 'Node':
        # print(data)
        if not data:
            return None
        
        s = deque(data.split('.'))
        root = Node(int(s.popleft()))

        def helper(node):
            if not s:
                return
            
            while s[0] != '#':
                v = int(s.popleft())
                child = Node(v)
                node.children.append(child)
                helper(child)
            s.popleft() # discard #
        
        helper(root)
        return root

572. Subtree of Another Tree

思路:检查左边再检查右边子树。没有看答案一次过。

class Solution(object):
    def isSubtree(self, s, t):
        """
        :type s: TreeNode
        :type t: TreeNode
        :rtype: bool
        """
        stack = [s]
        while stack:
            node = stack.pop()
            if node.val == t.val and self.check(node, t):
                return True
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
                    
        return False
        
    
    def check(self, s1, t1):
        # check the tree is the same or not
        if s1 and t1 and s1.val == t1.val:
            if self.check(s1.left, t1.left) and self.check(s1.right, t1.right):
                return True
        
        if s1 is None and t1 is None:
            return True

426. Convert Binary Search Tree to Sorted Doubly Linked List

Convert a BST to a sorted circular doubly-linked list in-place. Think of the left and right pointers as synonymous to the previous and next pointers in a doubly-linked list.

Let's take the following BST as an example, it may help you understand the problem better:

We want to transform this BST into a circular doubly linked list. Each node in a doubly linked list has a predecessor and successor. For a circular doubly linked list, the predecessor of the first element is the last element, and the successor of the last element is the first element.

The figure below shows the circular doubly linked list for the BST above. The "head" symbol means the node it points to is the smallest element of the linked list.

Specifically, we want to do the transformation in place. After the transformation, the left pointer of the tree node should point to its predecessor, and the right pointer should point to its successor. We should return the pointer to the first element of the linked list.

The figure below shows the transformed BST. The solid line indicates the successor relationship, while the dashed line means the predecessor relationship.

思路:

 241

Step 1: Divide:
We divide tree into three parts: left subtree, root node, right subtree.
Convert left subtree into a circular doubly linked list as well as the right subtree.
Be careful. You have to make the root node become a circular doubly linked list.

Step 2: Conquer:
Firstly, connect left circular doubly linked list with the root circular doubly linked list.
Secondly, connect them with the right circular doubly linked list. Here we go!

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val, left, right):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution(object):
    def treeToDoublyList(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return 
        
        leftHead = self.treeToDoublyList(root.left)
        rightHead = self.treeToDoublyList(root.right)
        
        root.left = root
        root.right = root
        return self.connect(self.connect(leftHead, root), rightHead)
        
    def connect(self, n1, n2):
        if not n1:
            return n2
        if not n2:
            return n1
        
        tail1 = n1.left  # 左边的最后一个即head的前一个
        tail2 = n2.left  # 右边的最后一个同理
        
        tail1.right = n2
        n2.left = tail1
        
        tail2.right = n1
        n1.left = tail2
        
        return n1
        
        

124. Binary Tree Maximum Path Sum 

class Solution(object):
    def maxPathSum(self, root):
        # left max + right max + cur node
        self.res = float('-inf')
        def maxPath(root):
            if not root:
                return 0
            left = max(0, maxPath(root.left))
            right = max(0, maxPath(root.right))
            self.res = max(self.res, left+right+root.val)
            return max(left, right) + root.val  # 注意这里只能是 左边或者右边的path加当前节点
        maxPath(root)
        return self.res

543. Diameter of Binary Tree

和上题几乎一样

class Solution(object):
    def diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.re = 0
        self.pathDown(root)
        return self. re
    
    def pathDown(self, node):
        if not node:
            return 0
        
        left = self.pathDown(node.left)
        right = self.pathDown(node.right)
        self.re = max(self.re, left + right)
        
        return max(left, right) + 1

314. Binary Tree Vertical Order Traversal

Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).

If two nodes are in the same row and column, the order should be from left to right.

class Solution(object):
    def verticalOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        
        cols = collections.defaultdict(list)
        queue = [(root, 0)]
        
        while queue:
            node, col = queue.pop(0)
            if node:
                cols[col].append(node.val)
                queue.append((node.left, col-1))
                queue.append((node.right, col+1))
                
        return [cols[i] for i in sorted(cols)]

99. Recover Binary Search Tree

这种格式的是按照inorder顺序来的: 

根据inorder 比较时候,当前节点在左时候(preNode)比curNode(父节点)小,  当前节点(preNode)在父节点的时候:比右子树 最左的节点小 

class Solution(object):
    def recoverTree(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        self.firstNode = None
        self.secondNode = None
        self.preNode = TreeNode(float('-inf'))
        
        self.traverse(root)
        self.firstNode.val, self.secondNode.val = self.secondNode.val, self.firstNode.val
            
        
    def traverse(self, node):
        if not node:
            return 
        
        self.traverse(node.left)
        if self.firstNode == None and self.preNode.val >= node.val:
            self.firstNode = self.preNode
        
        if self.firstNode and self.preNode.val >= node.val:
            self.secondNode = node
            
        self.preNode = node
            
        self.traverse(node.right)

285. Inorder Successor in BST

自己写的很长,但是OJ accept了。懒得研究为什么别人的那么短了。 

class Solution(object):
    def inorderSuccessor(self, root, p):
        """
        :type root: TreeNode
        :type p: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        self.find = False
        return self.helper(root, p.val)
    
    def helper(self, node, val):
        if not node:
            return 
        
        left = self.helper(node.left, val)
        if left: return left 
        
        if self.find:
            return node
        
        if node.val == val:
            self.find = True
            
        right = self.helper(node.right, val)
        if right: return right

652. Find Duplicate Subtrees

O(n) O(n) 


class Solution(object):
    def findDuplicateSubtrees(self, root):
        """
        :type root: TreeNode
        :rtype: List[TreeNode]
        """
        self.type_id_gen = 0
        type_to_freq = collections.defaultdict(int)
        type_to_id = {}
        duplicate = []
        
        def dfs(node):
            if not node:
                return -1
            type_id_left, type_id_right = dfs(node.left), dfs(node.right)
            tree_type = (node.val, type_id_left, type_id_right)
            print tree_type
            freq = type_to_freq[tree_type]
            if freq == 0:
                type_id = self.type_id_gen
                type_to_id[tree_type] = self.type_id_gen
                self.type_id_gen += 1
            elif freq == 1:
                type_id = type_to_id[tree_type]
                duplicate.append(node)
            else:
                type_id = type_to_id[tree_type]
            
            type_to_freq[tree_type] += 1
            return type_id
        
        dfs(root)
        return duplicate
                

def findDuplicateSubtrees(self, root, heights=[]):
    def getid(root):
        if root:
            id = treeid[root.val, getid(root.left), getid(root.right)]
            trees[id].append(root)
            return id
    trees = collections.defaultdict(list)
    treeid = collections.defaultdict()
    treeid.default_factory = treeid.__len__
    getid(root)
    return [roots[0] for roots in trees.values() if roots[1:]]

783. Minimum Distance Between BST Nodes

经典Inorder

class Solution(object):
    def minDiffInBST(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.re = float('inf')
        self.preNode = float('-inf')
        def inorder(node):
            if not node:
                return
            inorder(node.left)
            self.re = min(self.re, abs(node.val - self.preNode)) 
            self.preNode = node.val 
            inorder(node.right)
        inorder(root)
        return self.re

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值