代码随想录算法训练营第十八天 | 513. 找树左下角的值、112. 路径总和、106. 从中序与后序遍历序列构造二叉树

85 阅读2分钟

513. 找树左下角的值

代码随想录视频讲解

代码随想录文章讲解

迭代法层次遍历

  • return最后访问的值即可
  • 从右往左进队列
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        q = deque([root])
        res = None
​
        while q:
            l = len(q)
            for _ in range(l):
                cur = q.popleft()
                res = cur.val
                if cur.right:
                    q.append(cur.right)
                if cur.left:
                    q.append(cur.left)
​
        return res

递归法(使用dict存放层最左边的节点)

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        depth_map = {}
        depth = 0
​
        self.map_depth_to_value(root, depth, depth_map)
        return list(depth_map.items())[-1][1]
​
    def map_depth_to_value(self, root, depth, depth_map):
        # only record the left most node in each depth
        # root
        if depth not in depth_map:
            depth_map[depth] = root.val
​
        depth += 1
​
        # left
        if root.left:
            self.map_depth_to_value(root.left, depth, depth_map)
        # right
        if root.right:
            self.map_depth_to_value(root.right, depth, depth_map)

递归法(一直记录遍历到当前节点为止的最大深度和对应的最左边的节点)

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        left_node_val = None
        max_depth = -1
​
        def helper(cur, cur_depth):
            nonlocal max_depth, left_node_val
            
            # leaf node
            if not cur.left and not cur.right:
                if cur_depth > max_depth:
                    left_node_val = cur.val
                    max_depth = cur_depth
                    
            if cur.left:
                helper(cur.left, cur_depth+1)
            if cur.right:
                helper(cur.right, cur_depth+1)
​
        helper(root, 0)
​
        return left_node_val

112. 路径总和

代码随想录视频讲解

代码随想录文章讲解

递归法(计算所有path的和)

  • 前序遍历
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
​
        res = []
        path_sum = 0
        self.get_path_sum(root, path_sum, res)
        
        return targetSum in res
​
    def get_path_sum(self, root, path_sum, res):
      # root
        path_sum += root.val
        if not root.left and not root.right:
            res.append(path_sum)
      # left
        if root.left:
            self.get_path_sum(root.left, path_sum, res)
      # right
        if root.right:
            self.get_path_sum(root.right, path_sum, res)

递归法(更新target值)

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        
        # leaf node
        if not root.left and not root.right:
            return root.val == targetSum
​
        targetSum -= root.val
        # left or right
        return self.hasPathSum(root.left, targetSum) or self.hasPathSum(root.right, targetSum)

迭代法(栈模拟前序遍历)

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
​
        stack = deque([(root, 0)])
        while stack:
            cur, path_sum = stack.pop()
            path_sum += cur.val
​
            # leaf node
            if not cur.left and not cur.right and path_sum == targetSum:
                return True
​
            if cur.left:
                stack.append((cur.left, path_sum))
            if cur.right:
                stack.append((cur.right, path_sum))
​
        return False

113. 路径总和 II

递归法

  • 使用path[:]保留当时的path的值
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        if not root:
            return []
​
        def helper(root, remain):
            if not root.left and not root.right and remain == 0:
                res.append(path[:])
                return
​
            if root.left:
                path.append(root.left.val)
                helper(root.left, remain - root.left.val)
                path.pop()
            if root.right:
                path.append(root.right.val)
                helper(root.right, remain - root.right.val)
                path.pop()
​
        res, path = [], [root.val]
        helper(root, targetSum - root.val)
        return res

106. 从中序与后序遍历序列构造二叉树

代码随想录视频讲解

代码随想录文章讲解

递归法

  • 利用postorder和inorder的遍历顺序,不断找到子树的根节点并进行连接

    • 根节点为postorder的最后一个元素,利用这个元素去分割inorder(根节点元素在list中间,左右子树在两边)
    • 利用左右子树所包含的节点数是一样的特性,把在inorder中找到的左右子树的大小用来分割postorder(左子树在前,右子树在后)
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        if not inorder and not postorder:
            return None
​
        # root is the last value in postorder
        root_val = postorder[-1]
        
        # use root to partition inorder list
        index = inorder.index(root_val)
        left_in_part = inorder[:index]
        right_in_part = inorder[index+1:]
​
        # use left and right part to partition postorder list
        left_post_part = postorder[:len(left_in_part)]
        right_post_part = postorder[len(left_in_part):len(left_in_part)+len(right_in_part)]
​
        root = TreeNode(root_val)
        root.left = self.buildTree(left_in_part, left_post_part)
        root.right = self.buildTree(right_in_part, right_post_part)
​
        return root

105. 从前序与中序遍历序列构造二叉树

  • 一样的思路
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if not preorder and not inorder:
            return None
​
        # root is the first value in preorder
        root_val = preorder[0]
        
        # use root to partition inorder list
        index = inorder.index(root_val)
        left_in_part = inorder[:index]
        right_in_part = inorder[index+1:]
​
        # use left and right part to partition preorder list
        left_pre_part = preorder[1 : 1+len(left_in_part)]
        right_pre_part = preorder[1+len(left_in_part) : ]
​
        root = TreeNode(root_val)
        root.left = self.buildTree(left_pre_part, left_in_part)
        root.right = self.buildTree(right_pre_part, right_in_part)
​
        return root