当前位置: 首页 > news >正文

代码随想录第14天:(二叉树)

一、找树左下角的值(Leetcode 513)

递归法:

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        # 初始化最大深度为 -1,表示当前尚未遍历任何节点
        # 初始化 result 为 None,最终将存储最左边的节点值
        self.max_depth = -1  
        self.result = None
        
        # 从根节点开始深度优先遍历,初始深度为 0
        self.traversal(root, 0)
        
        # 返回遍历过程中记录的最左边节点的值
        return self.result
    
    def traversal(self, node, depth):
        # 如果当前节点为空,直接返回(递归结束条件)
        if not node:
            return
        
        # 如果当前节点的深度比最大深度大,说明找到了一个新的最深层
        # 更新最大深度和当前深度下最左边的节点值
        if depth > self.max_depth:
            self.max_depth = depth
            self.result = node.val  # 记录当前深度的最左边节点值
        
        # 先递归遍历左子树,再遍历右子树
        # 左子树会先被访问,因此最左边的节点会先被更新为 result
        # 递归调用时,深度加 1
        self.traversal(node.left, depth + 1)
        
        # 同样,递归调用右子树,深度也加 1
        self.traversal(node.right, depth + 1)

迭代法:

from collections import deque

class Solution:
    def findBottomLeftValue(self, root):
        # 如果树为空,返回 0
        if root is None:
            return 0
        
        # 使用双端队列来实现队列操作,支持 O(1) 的 popleft 操作
        queue = deque()
        
        # 将根节点添加到队列中
        queue.append(root)
        
        # 记录最左边节点的值,初始为 0
        result = 0
        
        # 开始广度优先遍历(层序遍历)
        while queue:
            # 获取当前队列的大小,即当前层的节点数
            size = len(queue)
            
            # 遍历当前层的所有节点
            for i in range(size):
                # 从队列中弹出一个节点
                node = queue.popleft()
                
                # 如果是当前层的第一个节点,则更新 result 为该节点的值
                if i == 0:
                    result = node.val
                
                # 如果当前节点有左子节点,将左子节点加入队列
                if node.left:
                    queue.append(node.left)
                
                # 如果当前节点有右子节点,将右子节点加入队列
                if node.right:
                    queue.append(node.right)
        
        # 返回最左边的节点值(最底层最左的节点)
        return result

二、路径总和I(Leetcode 112)

遍历的路线,并不要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示。

class Solution:
    # 递归辅助函数:遍历树的每一条路径
    def traversal(self, cur: TreeNode, count: int) -> bool:
        # 1. 如果当前节点是叶子节点,并且路径和等于0,返回 True
        if not cur.left and not cur.right and count == 0:  # 叶子节点且路径和为0
            return True
        
        # 2. 如果是叶子节点,但路径和不为0,返回 False
        if not cur.left and not cur.right:  # 叶子节点,但路径和不为0
            return False
        
        # 3. 否则,继续遍历左右子树
        
        # 处理左子树
        if cur.left:  # 如果有左子树
            count -= cur.left.val  # 减去当前节点的值,递归检查左子树
            if self.traversal(cur.left, count):  # 递归调用左子树
                return True  # 如果左子树存在符合条件的路径,直接返回 True
            count += cur.left.val  # 回溯,撤销左子树的减法

        # 处理右子树
        if cur.right:  # 如果有右子树
            count -= cur.right.val  # 减去当前节点的值,递归检查右子树
            if self.traversal(cur.right, count):  # 递归调用右子树
                return True  # 如果右子树存在符合条件的路径,直接返回 True
            count += cur.right.val  # 回溯,撤销右子树的减法
        
        # 如果左右子树都没有符合的路径,返回 False
        return False
    
    # 主函数:判断从根节点到叶子节点是否有路径和为 targetSum
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:  # 空树没有路径
            return False
        # 从根节点开始递归,路径和初始化为 targetSum - root.val
        return self.traversal(root, targetSum - root.val)



三、路径总和II (Leetcode 113)

路径总和ii要遍历整个树,找到所有路径,所以递归函数不要返回值!

class Solution:
    def __init__(self):
        # 初始化结果列表和路径列表
        self.result = []  # 存储所有符合条件的路径
        self.path = []  # 存储当前路径

    def traversal(self, cur, count):
        # 1. 遇到叶子节点且路径和等于目标和
        if not cur.left and not cur.right and count == 0:
            # 如果是叶子节点,且路径和符合条件,记录当前路径
            self.result.append(self.path[:])  # 将当前路径复制到结果中
            return

        # 2. 遇到叶子节点但路径和不为0,直接返回
        if not cur.left and not cur.right:
            return

        # 3. 递归遍历左子树
        if cur.left:
            self.path.append(cur.left.val)  # 将左子节点的值加入路径
            count -= cur.left.val  # 更新路径和
            self.traversal(cur.left, count)  # 递归遍历左子树
            count += cur.left.val  # 回溯:撤销对路径和的修改
            self.path.pop()  # 回溯:从路径中移除最后一个节点

        # 4. 递归遍历右子树
        if cur.right:
            self.path.append(cur.right.val)  # 将右子节点的值加入路径
            count -= cur.right.val  # 更新路径和
            self.traversal(cur.right, count)  # 递归遍历右子树
            count += cur.right.val  # 回溯:撤销对路径和的修改
            self.path.pop()  # 回溯:从路径中移除最后一个节点

        return

    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        # 清空结果和路径,以确保每次调用时数据是干净的
        self.result.clear()
        self.path.clear()

        # 如果根节点为空,返回空结果
        if not root:
            return self.result

        # 先将根节点的值加入路径
        self.path.append(root.val)
        # 从根节点开始递归,更新路径和为 targetSum - 根节点的值
        self.traversal(root, targetSum - root.val)
        # 返回所有符合条件的路径
        return self.result

四、从中序与后序遍历序列构造二叉树(Leetcode 106)

相关文章:

  • CasaOS香橙派安装HomeAssistant智能家居系统并实现远程管理家中智能设备
  • 微服务简述
  • Backtrader从0到1——第一个回测策略
  • Gerapy二次开发:用户管理专栏主页面开发
  • 算法训练之动态规划(二)
  • 深度解析强化学习:原理、算法与实战
  • 【LunarVim】解决which-key 自定义键位注册不成功问题
  • adb|scrcpy的安装和配置方法|手机投屏电脑|手机声音投电脑|adb连接模拟器或手机
  • IDEA、Webstorm使用账号密码登录Gitlab
  • 145.WEB渗透测试-信息收集-小程序、app(16)
  • CExercise_09_1结构体和枚举_1定义一个Date结构体,包含年、月、日数据项。编写一个函数,计算两个日期之间的天数差
  • 前端笔记-ECMAScript语法概览
  • 在Linux系统命令行如何使用deepseek官方API调用AI大模型?
  • python:all列表
  • 平时工作忙,报考学习PMP要怎么规划?需要多长时间?
  • CentOS Stream release 9安装 MySQL(一)
  • 用VScode来编写前后端——构建基础框架
  • 信息系统项目管理师-第十五章-项目风险管理
  • 向量密码本:Threejs 用加减乘除驯服 3D 空间
  • 我开源了一个“宝藏”开源项目
  • 创网站需要什么/天津网站推广
  • 湖北省利川市建设局网站/seo优化招商
  • 武汉建设公司网站/培训推广 seo
  • 河北公司网站建设效果/2023新闻大事10条
  • 如何用dw制作简单网页/seo还能赚钱吗
  • 做网站好找工作吗/广州seo诊断