Leetcode刷题记录(代码随想录day16)

Day 16

二叉树各种遍历的应用



回溯

513. 找树左下角的值

给定一个二叉树的根节点root,请找出该二叉树的最底层最左边节点的值。假设二叉树中至少有一个节点。

:回溯(递归)或层序遍历

# 递归法
class Solution:
    def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        maxDepth = -1
        result = 0
        if root == None:
            return 0
        def findMax(root, depth):
            nonlocal maxDepth, result  # 使用函数外定义的变量
            if not root.left and not root.right:
                if depth > maxDepth:  # 更新最大深度和最左叶子节点
                    maxDepth = depth
                    result = root.val
            if root.left:
                depth += 1
                findMax(root.left, depth)
                depth -= 1  # 要回溯,也就是回到上一层继续查找,所以层数要-1
            if root.right:
                depth += 1
                findMax(root.right, depth)
                depth -= 1  # 要回溯
            return
        findMax(root, 0)
        return result

# 迭代
from collections import deque
class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        queue = deque()
        if root: 
            queue.append(root)
        result = 0
        while queue: 
            q_len = len(queue)
            for i in range(q_len): 
                if i == 0: 
                    result = queue[i].val 
                cur = queue.popleft()
                if cur.left: 
                    queue.append(cur.left)
                if cur.right: 
                    queue.append(cur.right)
        return result

112. 路径总和

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

:递归函数什么时候需要返回值?什么时候不需要返回值?总结为如下三点:

  1. 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
  2. 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
  3. 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

如题,只需要求其中一条路,就需要返回值,而后面的113题需要求路径,要遍历整棵树,就不需要返回值。

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root == None:
            return False
        def countSum(root, count):
            if root.left == None and root.right == None:
                if count == 0:
                    return True
                else:
                    return False
            if root.left:
                # 隐藏回溯写法,因为传入的是count-val,count不变,所以回溯被省略了
                if countSum(root.left, count-root.left.val):
                    return True
            if root.right:
                # 回溯写法
                count -= root.right.val
                if countSum(root.right, count):
                    return True
                count += root.right.val
            return False
        return countSum(root, targetSum-root.val)

113. 路径总和 II(中等)

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

:如上题所说,需要遍历整棵树并找出所有路径。

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        result = []
        path = []
        if not root:
            return result
        def findPath(root, count):
            if root.left == None and root.right == None:
                if count == 0:
                    result.append(path[:])  # 要加个[:]否则result和path共内存,pop后会改变result
                else:
                    return
            if root.left:
                path.append(root.left.val)
                findPath(root.left, count - root.left.val)
                path.pop()
            if root.right:
                path.append(root.right.val)
                findPath(root.right, count - root.right.val)
                path.pop()
            return path
        path.append(root.val)
        findPath(root, targetSum - root.val)
        return result


遍历确定二叉树

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

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

:如何根据遍历进行求解呢?中序遍历是[左侧树],根,[右侧树],后序遍历是[左侧树],[右侧树],根,因此后序的最后一个点为根,找到中序中的根,即可找出左侧树和右侧树。再在后序中找到左侧树和右侧树的根,以此类推。

这种一层一层切割的方法,适合用递归。具体分为以下几步:
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 1.判断空节点
        if not postorder:
            return
        # 2.后序数组最后一个是节点
        node_val = postorder[-1]
        node = TreeNode(node_val)
        # 3.以节点切割中序数组
        node_index = inorder.index(node_val)
        # 4.切割中序数组
        left_inorder = inorder[:node_index]
        right_inorder = inorder[node_index+1:]
        # 5.切割后序数组
        length = len(left_inorder)
        left_postorder = postorder[:length]
        right_postorder = postorder[length:-1]
        # 6.递归
        node.left = self.buildTree(left_inorder,left_postorder)
        node.right = self.buildTree(right_inorder,right_postorder)
        return node

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

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

:类似的

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 1.判断空节点
        if not preorder:
            return
        # 2.先序数组第一个是节点
        node_val = preorder[0]
        node = TreeNode(node_val)
        # 3.以节点切割中序数组
        node_index = inorder.index(node_val)
        # 4.切割中序数组
        left_inorder = inorder[:node_index]
        right_inorder = inorder[node_index+1:]
        # 5.切割先序数组
        length = len(left_inorder)
        left_preorder = preorder[1:length+1]
        right_preorder = preorder[length+1:]
        # 6.递归
        node.left = self.buildTree(left_preorder,left_inorder)
        node.right = self.buildTree(right_preorder,right_inorder,)
        return node
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值