代码随想录算法训练营Day18 | 513.找树左下角的值、112. 路径总和(以及113.)、106.从中序与后序遍历序列构造二叉树(以及105.) | Python | 个人记录向

文章讲述了在编程中遇到的几个与二叉树相关的算法问题,包括找树左下角的值、路径总和、路径总和II以及通过中序和后序遍历序列构造二叉树。文章强调了层序遍历、递归和迭代方法的应用,以及如何利用中序+后序或前序+中序构造唯一二叉树。
摘要由CSDN通过智能技术生成

513.找树左下角的值

代码随想录:513.找树左下角的值
Leetcode:513.找树左下角的值

做题

层序遍历。

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root:
            return None
        queue = collections.deque()
        queue.append(root)
        while queue:
            for i in range(len(queue)):
                if i == 0:
                    cur = queue[0].val
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return cur

看文章

层序遍历很简单,主要看递归,递归就是记录一下当前深度,然后在深度变大时更新一下result。

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        self.max_depth = float('-inf')
        self.result = None
        self.traversal(root, 0)
        return self.result
    
    def traversal(self, node, depth):
        if not node.left and not node.right:
            if depth > self.max_depth:
                self.max_depth = depth
                self.result = node.val
            return
        
        if node.left:
            depth += 1
            self.traversal(node.left, depth)
            depth -= 1
        if node.right:
            depth += 1
            self.traversal(node.right, depth)
            depth -= 1

112. 路径总和

代码随想录:112. 路径总和
Leetcode:112. 路径总和

做题

瞅了一眼之前做的记录,发现很简单,也很快get到思路…

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

看文章

递归比较简单,迭代比较麻烦。

113.路径总和ii

Leetcode:113.路径总和ii

做题

按照直接找路径的思路写了一下,思路差不多,但细节有bug。主要有2个点:

  1. 我传入的是path这个参数,所以在保存到res的时候,要先copy一下再存入(或者用list(path)也行,总之就是要另存或转换为一个新对象再存入),否则res里的结果会根据path的变化而变化。
  2. 必须找到叶子结点才能终止。
  3. targetSum可能是负数,故不需要判断节点值是否小于targetSum,只需要都搜索到叶子结点即可。

最后AC的代码如下:

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        if not root:
            return []
        res = []
        path = []
        self.findPath(root, targetSum, res, path)
        return res

    def findPath(self, node, target, res, path):
        if node.val == target and not node.left and not node.right:
            path.append(node.val)
            res.append(path.copy())
            path.pop()
        else:
            path.append(node.val)
            if node.left:
                self.findPath(node.left, target - node.val, res, path)
            if node.right:
                self.findPath(node.right, target - node.val, res, path)
            path.pop()

看文章

同样是迭代比较麻烦,就先不看了。

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

重点题目!!!笔试没做出来的题!!!
代码随想录:106.从中序与后序遍历序列构造二叉树
Leetcode:106.从中序与后序遍历序列构造二叉树

做题

直接看文章。

看文章

已知:中序、后序。
具体步骤如下:

  1. 后序数组是左右中,root节点一定是最后一个值。
  2. 根据root节点回到中序数组,root左边的节点一定是root的左子树,右边的节点一定是root的右子树。
  3. 根据左子树和右子树回到后序数组,切分出左右子树。此时回到1,分别从左右子树递归寻找。
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        # 第一步: 特殊情况讨论: 树为空. (递归终止条件)
        if not postorder:
            return None

        # 第二步: 后序遍历的最后一个就是当前的中间节点.
        root_val = postorder[-1]
        root = TreeNode(root_val)

        # 第三步: 找切割点.
        separator_idx = inorder.index(root_val)

        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left = inorder[:separator_idx]
        inorder_right = inorder[separator_idx + 1:]

        # 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
        # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
        postorder_left = postorder[:len(inorder_left)]
        postorder_right = postorder[len(inorder_left): len(postorder) - 1]

        # 第六步: 递归
        root.left = self.buildTree(inorder_left, postorder_left)
        root.right = self.buildTree(inorder_right, postorder_right)
         # 第七步: 返回答案
        return root

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

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

做题

理解思路后,只需要调整下逻辑。代码如下:

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if not preorder:
            return None

        root_val = preorder[0]
        root = TreeNode(root_val)

        separator_index = inorder.index(root_val)
        inorder_left = inorder[:separator_index]
        inorder_right = inorder[separator_index + 1:]

        preorder_left = preorder[1: len(inorder_left)+1]
        preorder_right = preorder[len(inorder_left)+1:]
        
        root.left = self.buildTree(preorder_left, inorder_left)
        root.right = self.buildTree(preorder_right, inorder_right)
        return root

看文章

思路一致。

以往忽略的知识点小结

  • 可以在递归时记录深度,以找到最底层的节点
  • 使用中序+后序、前序+中序构造唯一二叉树。具体操作为:
    1. 使用前序/后序的特点,找到唯一的“中”,回到中序数组进行分割,分割出左右子树的中序数组;
    2. 根据分割的左右子树长度,回到前序/后序数组,分割出左右子树的前序/后序数组;
    3. 分别通过左子树的中序+前序/后序数组、右子树的中序+前序/后序数组,递归构建二叉树即可。
  • 如果有二叉树有重复值,上面的问题还能求解吗?不能。
  • 前序+后序无法构造唯一二叉树。

个人体会

完成时间:1h50min。
心得:注意在递归时可以记录深度;使用中序+后序、前序+中序构造唯一二叉树,总体思路是递归,首先是在前序/后序数组找到“中”,回到中序做分割,然后再根据分割的长度,再分割前序/后序数组,得到左右子树各自的中序+前序/后序数组,最后递归即可。使用中序+后序、前序+中序构造唯一二叉树是重点,之前笔试折戟过,必须掌握!!!

  • 35
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值