算法学习 day16 二叉树4

77 阅读4分钟

513. 找树左下角的值

文章讲解

视频讲解

题目:给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

 

示例 1:

输入: root = [2,1,3]
输出: 1

示例 2:

****

输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7

解题思路1: 层序遍历

  • 时间复杂度:O(n),其中 n 是二叉树的节点数目。
  • 空间复杂度:O(n),如果二叉树是满完全二叉树,那么队列 q 最多保存 ⌈n/2⌉个节点。
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root:
            return root
        queue = [root]
        result = -1 # 记录最底层左边的节点值
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.pop(0)
                if i == 0:
                    result = node.val
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)

        return result
        
# 从右到左的层次遍历,最后一个节点就是最底层左边的节点
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root:
            return root
        queue = [root]
        result = -1 # 记录最底层左边的节点值
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.pop(0)
                result = node.val
                # 先右再左
                if node.right:
                    queue.append(node.right)
                if node.left:
                    queue.append(node.left)

        return result

解题思路2

递归时先遍历左再右,如果左边达到最大深度了就更新结果。

  • 时间复杂度:O(n),其中 n 是二叉树的节点数目。需要遍历 n 个节点。
  • 空间复杂度:O(n),递归栈需要占用 O(n) 的空间。
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        # if not root:
            # return -1
        self.maxDepth = -1
        self.result = 0
        self.traverse(root, depth=1) # check depth
        return self.result

    def traverse(self, root, depth=0):
        # 终止条件
        if not root.left and not root.right:
            if depth > self.maxDepth:
                self.maxDepth = depth
                self.result = root.val

        # 先遍历左再右,这样优先更新最大深度的左节点
        if root.left:
            self.traverse(root.left, depth+1)
        if root.right:
            self.traverse(root.right, depth+1)        

总结

最简单的是层次遍历,记录最后一层第一个节点值即可;或者从右往左层次遍历,记录最后一个节点;dfs时候需要记录depth,然后由于对中间节点没有操作,只需要保证先左孩子再右孩子即可。

112. 路径总和

文章讲解

视频讲解

题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

 

示例 1:

输入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出: true
解释: 等于目标和的根节点到叶节点路径如上图所示。

示例 2:

输入: root = [1,2,3], targetSum = 5
输出: false
解释: 树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

解题思路

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        # 叶子节点:
        if not root.left and not root.right:
            return root.val == targetSum
        
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum-root.val)


class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        return self.traverse(root, root.val, targetSum)

    def traverse(self, root, current_sum, targetSum) -> bool:
        # 检查叶子节点
        if not root.left and not root.right:
            return current_sum == targetSum

        found_path = False

        if root.left:
            found_path = self.traverse(root.left, current_sum + root.left.val, targetSum)

        if root.right:
            found_path = found_path or self.traverse(root.right, current_sum + root.right.val, targetSum)

        return found_path

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

文章讲解

视频讲解

题目:给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

 

示例 1:

输入: inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出: [3,9,20,null,null,15,7]

image.png

解题思路

  • 时间复杂度:O(n),其中 n 是树中的节点个数。
  • 空间复杂度:O(n),需要使用 O(n) 的空间存储哈希表,以及 O(h)(其中 h 是树的高度logn)的空间表示递归时栈空间。这里 h<n,所以总空间复杂度为 O(n)
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        self.val2idx = {}
        for i in range(len(inorder)):
            self.val2idx[inorder[i]] = i
        return self.build(inorder, 0, len(inorder)-1, postorder,0, len(postorder)-1)

    def build(self, inorder, in_start, in_end, postorder, post_start, post_end):
        if in_start > in_end:
            return None

        root_val = postorder[post_end]
        root_idx = self.val2idx[root_val]
        left_size = root_idx - in_start

        root = TreeNode(val=root_val)
        root.left = self.build(inorder,in_start, root_idx -1,
                               postorder,post_start, post_start +left_size-1)
        root.right = self.build(inorder,root_idx+1, in_end,
                                postorder, post_start+left_size, post_end-1)
        return root