Leetcode刷题记录111-120,python语言

111 二叉树的最小深度(队列queue)

队列queue,遍历每一层的节点,同时从队列queue弹出自己节点,又加入子节点到queue。

# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0 # 深度为零
        queue = [root] # 0层根节点,每一层
        depth = 1 # 根节点算一个深度
        while queue: # 该层节点非空
            n = len(queue) # 当前层的节点数量
            for _ in range(n): # 遍历当前层所有节点,同时队列弹出自己节点,把下一层加到queue队列
                node = queue.pop(0)
                if not node.left and not node.right: # !!当没有左右子节点, depth就不会加一,而是直接return最小深度 ,从根节点到最近叶子节点的最短路径上的节点数量。
                    return depth
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            depth += 1
        return depth

法二 ,递归

# 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 minDepth(self, root: Optional[TreeNode]) -> int:
         # 如果根节点为空,则深度为0
        if not root:
            return 0
        
        # 如果左子树为空,则递归计算右子树的最小深度
        if not root.left:
            return 1 + self.minDepth(root.right)
        
        # 如果右子树为空,则递归计算左子树的最小深度
        if not root.right:
            return 1 + self.minDepth(root.left)
        
        # 分别计算左右子树的最小深度,取最小值并加1
        return 1 + min(self.minDepth(root.left), self.minDepth(root.right))

112 路径总和 (递归)

这段代码定义了一个TreeNode类用来表示二叉树的节点。hasPathSum函数接受一个根节点root和一个目标和targetSum作为参数,用来判断是否存在从根节点到叶子节点的路径和等于目标和。
在hasPathSum函数中,首先检查当前节点是否为空,如果为空则直接返回False。然后,判断当前节点是否为叶子节点且值等于目标和,如果是,则返回True。如果不是叶子节点,则递归地检查其左子树和右子树,并传入更新后的目标和(减去当前节点值)。
最后,函数会返回左右子树中是否存在满足条件的路径。

# 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:
        if not root:
            return False
        
        # 如果当前节点是叶子节点并且其值等于目标和,则返回True
        if not root.left and not root.right and root.val == targetSum: # 注意这里两个not,还有两个and
            return True
        
        # 递归检查左子树和右子树
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)

113 路径总和 II (递归回溯dfs)

这段代码定义了一个TreeNode类用来表示二叉树的节点。pathSum函数接受一个根节点root和一个目标和targetSum作为参数,返回所有从根节点到叶子节点的路径,使得路径上节点值的和等于目标和。

在pathSum函数中,首先初始化一个空数组res用来存储满足条件的路径。然后定义内部递归函数dfs,它接受当前节点node、剩余目标和target和当前路径path作为参数。

在dfs函数中,首先将当前节点的值加入路径path中。然后检查当前节点是否为叶子节点且节点值等于剩余目标和,如果是,则将该路径添加到结果数组res中。接着递归调用左子树和右子树,并更新剩余目标和。最后,弹出当前节点值,以便进行回溯处理其他路径。

最后,在主函数中调用dfs函数,并返回存储路径的结果数组res。

# 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]]:
        res = [] # 存储满足条件的路径
    
        def dfs(node, target, path): # 传入,当前节点node、剩余目标和target和当前路径path
            if not node: # 当前节点为空 , 直接返回
                return
            
            path.append(node.val) # 节点值加入path小list
            
            if not node.left and not node.right and node.val == target: # 没有子节点,当前节点值等于目标
                res.append(path.copy()) # 将该路径小list加入res
            
            dfs(node.left, target - node.val, path) #递归,左子节点
            dfs(node.right, target - node.val, path) 
            
            path.pop() # 回溯
        
        dfs(root, targetSum, [])

        return res

114 二叉树展开为链表

这段代码首先定义了TreeNode类表示二叉树节点,然后定义了flatten函数来展开二叉树。在flatten函数中,我们首先递归地处理左右子树,然后将当前节点的右子树接到左子树的最右边节点之后,最后将左子树作为新的右子树。

# 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 flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if not root:
            return
        
        # 递归处理左右子树
        self.flatten(root.left) # 先左子树
        self.flatten(root.right)
        
        temp = root.right  # 因为先序遍历,先把右子节点存起来,
        root.right = root.left # 将左子节点放到右子节点位置,这里和题目要求一致
        root.left = None # 左子节点令为空null
        
        # ,将原来右子树接到该节点后面
        while root.right: # 左子节点非空,while循环,不断循环右子节点非空的话,相当于左子树非空。背一下
            root = root.right # 这里是左子节点作为根节点,
        root.right = temp # 这一步就是把temp存的右子节点,放在左子节点的下一层了,形成单链表

116 填充每个节点的下一个右侧节点指针 (比较复杂,链表,二叉树)

这个解决方案使用了层次遍历的思想,通过迭代地遍历每一层节点,并设置它们的next指针来连接同一层的节点。
在这里插入图片描述

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if not root:
            return None
        
        level_start = root
        while level_start.left:  # 如果存在下一层
            curr = level_start # curr为根节点,定义curr
            while curr:  # 遍历当前层的所有节点
                curr.left.next = curr.right  # 左节点的next指向右节点。类似链表节点
                if curr.next:  # 如果存在下一个节点。这里就是说curr为左子节点,存在右子节点,不为空
                    curr.right.next = curr.next.left  # 右节点的next指向当前节点的next节点的左节点。如图,节点3指向4,root.right.next 指向,root.next.left。
                curr = curr.next  # 移动到当前层的下一个节点。直到curr为空。
            level_start = level_start.left  # 移动到下一层的最左节点。变为下一层。
        return root
        

117 填充每个节点的下一个右侧节点指针II (比较复杂,链表,二叉树)

法一

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        node = root
        while node:
            dummy = Node()
            nxt = dummy
            while node:
                if node.left:
                    nxt.next = node.left
                    nxt = nxt.next
                if node.right:
                    nxt.next = node.right
                    nxt = nxt.next
                node = node.next
            node = dummy.next
        return root
        

法二,我们定义了一个树节点类 TreeNode,其中包含一个 next 指针,用于指向同一层级中的下一个节点。
我们定义了一个 Solution 类,其中包含了解决问题的方法 connect。
在 connect 方法中,我们使用层序遍历的方式来逐层处理树节点的连接。
我们用 level_start 变量来表示每一层的起始节点,然后在每一层内部使用 prev 变量来表示前一个节点,以便进行连接。
在遍历每一层的节点时,我们首先处理左子节点,然后处理右子节点,并且更新 prev 变量。
在遍历完当前层的所有节点后,将 level_start 更新为下一层的起始节点,以便继续处理下一层。
最后返回根节点 root。

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        
        # 用于遍历每一层的节点
        level_start = root
        
        while level_start:
            # 初始化下一层的起始节点和前一个节点
            next_level_start = None
            prev = None
            
            # 遍历当前层的节点
            current = level_start
            while current:
                # 处理左子节点
                if current.left:
                    if prev:
                        prev.next = current.left
                    else:
                        next_level_start = current.left
                    prev = current.left
                
                # 处理右子节点
                if current.right:
                    if prev:
                        prev.next = current.right
                    else:
                        next_level_start = current.right
                    prev = current.right
                
                # 移动到当前层的下一个节点
                current = current.next
            
            # 移动到下一层的起始节点
            level_start = next_level_start
        
        return root
        

120 三角形最小路径和 (动态规划)

函数定义:

minimumTotal(self, triangle: List[List[int]]) -> int:这个方法接受一个二维列表 triangle,表示一个三角形。列表中的每个元素是一个一维列表,代表三角形的一行。
特殊情况处理:

if not triangle: return 0:如果输入的三角形为空,直接返回0。
初始化:

min_path_sum = triangle[-1]:创建一个列表 min_path_sum,用来存储每一层的最小路径和。初始时,将其设置为三角形的最后一行,因为从底部开始计算路径和。
动态规划计算:

从倒数第二行开始向上遍历三角形:
for row in range(len(triangle) - 2, -1, -1):
对于每一行的每一个元素,更新其最小路径和:
min_path_sum[col] = triangle[row][col] + min(min_path_sum[col], min_path_sum[col + 1])
这里利用了动态规划的思想,每次更新时选择当前元素下方两个相邻元素中的较小值,并加上当前元素的值,得到当前位置的最小路径和。
返回结果:

return min_path_sum[0]:最后,min_path_sum 的第一个元素就是从顶部到底部的最小路径和,返回这个值作为最终结果。
这种解法的时间复杂度为 ( O(n^2) ),其中 ( n ) 是三角形的行数,空间复杂度为 ( O(n) ),因为只使用了一个长度为 ( n ) 的列表来存储路径和。

class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        if not triangle:
            return 0
         # Initialize a list to store the minimum path sums for each level of the triangle
        min_path_sum = triangle[-1] # 存的倒数第一层的值
        
        # Traverse the triangle from bottom to top
        for row in range(len(triangle) - 2, -1, -1): # 从倒数第二行开始向上遍历。 因为min_path_sum存最早存的倒数第一层的值,所以row从倒数第二开始
            for col in range(len(triangle[row])):
                # Update the current element with the minimum path sum starting from it
                min_path_sum[col] = triangle[row][col] + min(min_path_sum[col], min_path_sum[col + 1]) # min取最小,倒数第一层的值。进行不断更新累计
        
        # The top element of min_path_sum now contains the minimum path sum
        return min_path_sum[0]
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值