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

一、LeetCode513.找树左下角的值

        1:题目描述(513. 找树左下角的值

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

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

        2:解题思路

# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
        # 层序遍历
        # queue = []
        # result = []
        # if not root:
        #     return None
        # queue.append(root)
        # while queue:
        #     q_len = len(queue)
        #     res = []
        #     while q_len:
        #         node = queue.pop(0)
        #         q_len -= 1
        #         res.append(node.val)
        #         if node.left:
        #             queue.append(node.left)
        #         if node.right:
        #             queue.append(node.right)
        #     result.append(res)
        # return result[-1][0]

        # 递归
        maxpath = -float("INF")       # 最大深度,初始为最小值
        result = 0
        def leftvalue(root, depth):
            if root.left == None and root.right == None:
                nonlocal maxpath, result
                # 当遇到叶子节点时,判断当前深度与最大深度的值
                if depth > maxpath:
                    maxpath = depth         # 将当前深度赋值给最大深度
                    result = root.val       # 并将此时叶子节点的值,复制给result
            if root.left:
                depth += 1                  # 遍历节点的左节点,深度+1
                leftvalue(root.left, depth)
                depth -= 1                  # 遍历节点的左节点结束后,深度需要-1,进行回溯
            if root.right:
                depth += 1
                leftvalue(root.right, depth)
                depth -= 1
            return result
        res = leftvalue(root, 0)
        return res

二、LeetCode112. 路径总和

        1:题目描述(112. 路径总和

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

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

        2:解题思路

# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        # # 递归
        # # 将左右路径的节点值相加的和,添加到一个数组中,最后去判断targetSum是否存在数组中
        # # res用来存储路径
        # # res_sum用来存储每个路径的和
        # def pathSum(root, res, res_sum):
        #     if root == None:
        #         return 0
        #     res.append(root.val)       # 将节点添加到路径res中
        #     if root.left == None and root.right == None:
        #         # 若当前节点的左右子节点均为None,说明节点是叶子节点,已经到了路径的最后一个节点
        #         path_sum = sum(res)    # 求路径的和
        #         res_sum.append(path_sum)    
        #         return res_sum
        #     if root.left:
        #         pathSum(root.left, res, res_sum)   # 遍历节点的左子树
        #         res.pop()             # 回溯,将添加的节点,从路径中弹出,回到上一个节点
        #     if root.right:
        #         pathSum(root.right, res, res_sum)
        #         res.pop()
        #     return res_sum
        # if not root:
        #     return False
        # res = pathSum(root, [], [])
        # if targetSum in res:
        #     return True
        # else:
        #     return False

        # 递归
        def pathSum(cur, count):
            if cur.left == None and cur.right == None and count == 0:
                return True
            if cur.left == None and cur.right == None and count != 0:
                return False
            if cur.left:
                count -= cur.left.val
            # 因为有返回值,所以需要有变量来承接返回值,返回值为True或False,可用来直接进行判断
                # 如果返回的是True,则说明找到了一条符合要求的路径,需要将True一层一层的向上返回
                # 所以为True时,向上返回True
                if pathSum(cur.left, count): return True
                # 回溯,需要返回到上一个节点
                count += cur.left.val
            if cur.right:
                count -= cur.right.val
                if pathSum(cur.right, count): return True
                count += cur.right.val
            # 如果一直都没有True返回,则说明不存在一条符合要求的路径,返回False
            return False
        if not root:
            return False
        res = pathSum(root, targetSum-root.val)
        return res

三、LeetCode113.路径总和ii

        1:题目描述(113. 路径总和 II

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

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

        2:解题思路

# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        # 递归
        # import copy
        # def path(root, res, result):
        #     res.append(root.val)
        #     if root.left == None and root.right == None:
        #         # 节点的左右子节点为None,说明是叶子节点,已经到了路径的最后一个节点
        #         # 不能直接将res加入result中,因为res是在变的,使用深copy将res赋值给l
        #         l = copy.deepcopy(res)
        #         result.append(l)
        #         return result
        #     if root.left:
        #         path(root.left, res, result)
        #         # 回溯,遍历完一条路径后,回到当前节点的父节点
        #         res.pop()
        #     if root.right: 
        #         path(root.right, res, result)
        #         # 回溯,遍历完一条路径后,回到当前节点的父节点
        #         res.pop()
        #     return result
        # result_list = []
        # if not root:
        #     return result_list
        # res_list = path(root, [], [])
        # for i in range(len(res_list)):
        #     if targetSum == sum(res_list[i]):
        #         result_list.append(res_list[i])
        # return result_list

        # 递归
        def hasPath(cur, remain):
            if cur.left == None and cur.right == None and remain == 0:
                # 节点的左右子节点为None,并且路径的总值等于目标值了,说明找到了符合要求的路径
                # 将路径添加到resul中
                result.append(path[:])
            elif cur.left == None and cur.right == None and remain != 0:
                # 到了叶子节点,路径的总值与目标值的差值不为0,说明路径不满足要求,返回上层
                return 
            if cur.left:
                # 将左节点加入path路径中
                path.append(cur.left.val)
                # 减去左节点的值
                remain -= cur.left.val
                hasPath(cur.left, remain)
                # 回溯
                remain += cur.left.val
                path.pop()
            if cur.right:
                path.append(cur.right.val)
                remain -= cur.right.val
                hasPath(cur.right, remain)
                remain += cur.right.val
                path.pop()
            return result
        result = []
        path = []
        if not root:
            return []
        path.append(root.val)
        hasPath(root, targetSum-root.val)
        return result

四、LeetCode106.从中序与后序遍历序列构造二叉树

        1:题目描述(106. 从中序与后序遍历序列构造二叉树

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

        2:解题思路

# 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 buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[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数组的左、右半边
        # 中序数组大小一定是跟后序数组大小相同的
        # 后历序遍的顺序为:左、右、中
        # 左半边为左子树,右半边为右子树
        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

五、LeetCode105.从前序与中序遍历序列构造二叉树

        1:题目描述(105. 从前序与中序遍历序列构造二叉树

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

        2:解题思路

# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 第一步:特殊情况:树为空(递归终止条件)
        if not preorder:
            return None
        
        # 第二步:确定中间节点,前序遍历的第一个节点是当前的中间节点
        root_val = preorder[0]
        root = TreeNode(root_val)

        # 第三步:找切割点,在中序遍历中寻找切割点
        separator_idx = inorder.index(root_val)

        # 第四步:切割中序数组,分割左右子树
        inorder_left = inorder[:separator_idx]
        inorder_right = inorder[separator_idx+1:]

        # 第五步:切割前序数组,分割左右子树
        # 前序数组的长度与中序数组的长度一定相等
        preorder_left = preorder[1:1+len(inorder_left)]
        preorder_right = preorder[1+len(inorder_left):]

        # 第六步:递归
        root.left = self.buildTree(preorder_left, inorder_left)
        root.right = self.buildTree(preorder_right, inorder_right)

        return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练主要涵盖了Leetcode题目的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串到第一个出现的字符的索引。思路是使用双指针来遍字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有数组的元素进行平方,并按照非递减的顺返回结果。这里由于数组已经是有的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组到长度最小的子数组,使得子数组的和大于等于给定的目标。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值