找树左下角的值+路径总和+从前序和中序遍历序列构造二叉树(day18*)

        这篇可以主要关注一下如何确定递归时是否需要返回值。

LC513. 找树左下角的值

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

思路1 层序遍历

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        if not root: return -1
        # leverOrder
        from collections import deque
        que = deque()
        que.append(root)
        while que:
            size = len(que)
            for i in range(size):
                node = que.popleft()
                if i == 0:
                    ans = node.val
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return ans

思路2 深度优先方法要困难一些,递归判断结点是否是深度最大的叶子结点,只遍历,没有进行什么操作,所以不需要有返回值。这种写法是隐含了回溯的,不需要自己写,因为函数调用完形参就释放了。

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        def isleaf(root):
            return root and not root.left and not root.right
        # 深度优先 
        max_depth = 0
        target = root.val
        def dfs(root, depth):
            nonlocal max_depth, target
            if not root: return 
            depth += 1
            if isleaf(root):
                if depth > max_depth:
                    max_depth = depth
                    target = root.val
            dfs(root.left, depth)
            dfs(root.right, depth)
        dfs(root, 0)
        return target

下面这种写法是把回溯写出来了,因为depth一直在变的。

class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        def isleaf(root):
            return root and not root.left and not root.right
        
        leftval = root.val
        max_d = 0
        depth = 0
        
        def dfs(root):
            nonlocal leftval, max_d, depth
            if not root: return
            depth += 1
            if isleaf(root):
                if depth > max_d:
                    max_d = depth
                    leftval = root.val
            if root.left:
                dfs(root.left)
                depth -= 1
            if root.right:
                dfs(root.right)
                depth -= 1
            
        dfs(root)
        return leftval

LC112. 路径总和​​​​​​ 

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

下面是我自己的写法,虽然AC了(其中要注意ans写成nonlocal),但是问题是找到了目标路径和之后还是会进行一整个树的遍历。

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        def isleaf(root):
            return root and not root.left and not root.right
        # 先序遍历
        ans = False
        pathsum = 0
        def dfs(root, pathsum):
            nonlocal ans
            if not root: return 
            pathsum += root.val
            if isleaf(root):
                if pathsum == targetSum:
                    ans = True
            if root.left: dfs(root.left, pathsum)
            if root.right: dfs(root.right, pathsum)

        dfs(root,pathsum)
        return ans

本题搜索出一条符合条件的路径即可,所以递归一定要有返回值,遇到符合的路径要及时返回。下面的写法好多了。

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        def isleaf(root):
            return root and not root.left and not root.right
        # 先序遍历
        def dfs(root, pathsum) -> bool:
            pathsum += root.val
            # 叶子结点如果找到了路径和,True;否则False
            if isleaf(root):
                if pathsum == targetSum:
                    return True
                else:
                    return False
            # 如果左孩子里面找到了路径和,返回True
            if root.left: 
                if dfs(root.left, pathsum):
                    return True
            # 如果右孩子里面找到了路径和,返回True
            if root.right: 
                if dfs(root.right, pathsum):
                    return True
            # 都没有找到,返回False
            return False

        if not root: return False #这一行也重要
        return dfs(root,0)

LC113. 路径总和 II

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。

本题是需要遍历完整棵树,且不用处理递归返回值,就不需要返回值。

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        def isleaf(root):
            return root and not root.left and not root.right
        
        paths = []
        path = []
        def dfs(root, sum_pre):
            if not root: return
            path.append(root.val)
            sum_pre += root.val
            # print(sum_pre, path)
            if isleaf(root) and sum_pre == targetSum: #写的时候isleaf后面的(root)也忘了写,就变成了是否存在isleaf函数,就一直都是True。多花了时间调试,写的时候就要慢慢细致地写。
                paths.append(path[:]) #[:]不要忘了加
            if root.left:
                dfs(root.left, sum_pre)
                path.pop()
            if root.right:
                dfs(root.right, sum_pre)
                path.pop()
                
        dfs(root, 0)
        return paths

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

这题没有看答案一次AC了,大晚上的开心了好一会儿~这草稿也是只有自己能看懂了LOL。

本题需要遍历完整棵树,但需要对递归返回值(结点)进行处理(链接),所以需要有返回值。

# 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 find(self, nums, val):
        for i, num in enumerate(nums):
            if num == val:
                return i
        return -1

    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
       # def constructTree(inorder, postorder: List[int]) -> Optional[TreeNode]:
        if not inorder: return None
        if len(inorder) == 1: return TreeNode(inorder[0])
        m = postorder[-1]
        node = TreeNode(m)
        i = self.find(inorder, m)
        print(m,i)
        l_inorder = inorder[0:i]
        r_inorder = inorder[i+1:]
        l_postorder = postorder[0:i]
        r_postorder = postorder[i:-1]
        node.left = self.buildTree(l_inorder,l_postorder)
        node.right = self.buildTree(r_inorder,r_postorder)
        return node

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

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

和上题一样的写法,但写find函数时出现了小问题,要在循环结束时还没return才返回-1。

class Solution:
    def find(self, nums, val):
        for i, num in enumerate(nums):
            if num == val:
                return i
        return -1
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if not preorder: return None
        Node = TreeNode(preorder[0])
        mid = preorder[0]
        i = self.find(inorder, mid)
        l_inorder, r_inorder = inorder[0:i], inorder[i+1:]
        l_preorder, r_preorder = preorder[1:i+1], preorder[i+1:]
        Node.left = self.buildTree(l_preorder, l_inorder)
        Node.right = self.buildTree(r_preorder, r_inorder)
        return Node

看了答案之后发现在list中查找元素的时候,不需要自己写函数,用自身的index方法,直接i = inorder.index(mid)即可。

明天加油~ 

参考资料:​​​​​​​路径总和-代码随想录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值