leetcode—21.二叉树路径和相关题目leetcode总结

2023-10-30

引言

  树的求和属于树的题目中比较常见的,因为可以有几种变体,灵活度比较高,也可以考察到对于树的数据结构和递归的理解。

112. 路径总和

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

示例:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
在这里插入图片描述

思路1:递归

这道题是判断是否存在从根到叶子的路径和跟给定sum相同。树的题目基本都是用递归来解决,主要考虑两个问题:
如何把问题分治成子问题给左子树和右子树。这里就是看看左子树和右子树有没有存在和等于sum 减去当前结点值的路径,只要有一个存在,那么当前结点就存在路径。
考虑结束条件是什么︰
结束条件1:如果当前节点是空的,则返回false。
结束条件2:如果是叶子,那么如果剩余的sum等于当前叶子的值,则找到满足条件的路径,返回true。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        # 如果当前节点为空,则返回False
        if root == None:
            return False

        # 如果当前节点是叶子节点,并且剩余sum等于叶子节点值
        if root.left == None and root.right == None and root.val == sum:
            return True

        # 如果当前节点是非叶子节点,则对它的左右子树分别调用函数
        return self.hasPathSum(root.left,sum-root.val) or self.hasPathSum(root.right,sum-root.val)

思路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: TreeNode, targetSum: int) -> bool:
        # 使用栈的结构,将递归化为迭代
        if root == None:
            return False
        # 栈
        stack = [(root,targetSum)]
        while stack:
            node,sum = stack.pop()
            # 如果为叶子节点,判断叶子节点是否满足条件
            if node.left == None and node.right == None and node.val == sum:
                return True
            
            # 如果不为叶子节点,则将当前节点的孩子节点及剩余值压入栈
            if node.left != None:
                stack.append((node.left,sum-node.val))
            if node.right != None:
                stack.append((node.right,sum-node.val))

        return False

113. 路径总和 II

  这道题思路和112–路径总和是完全一样的,只是需要输出所有路径,所以需要数据结构来维护路径,添加两个参数,一个用来维护走到当前结点的路径,一个用来保存满足条件的所有路径,思路上递归条件和结束条件是完全一致的,空间上这里会依赖于结果的数量

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

示例:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

思路1:递归

# 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: TreeNode, targetSum: int) -> List[List[int]]:
        # 需要一个辅助函数(记录变量路径)
        def helper(root,sum,temp):
            # 判断根节点是否是空节点
            if root == None:
                return None

            # 如果是叶子节点,判断剩余值是否与叶子节点值相等
            if root.left == None and root.right == None and root.val == sum:
                temp += [root.val]
                res.append(temp)

            # 如果当前节点非叶子节点,则递归调用左右子树
            helper(root.left,sum-root.val,temp+[root.val])
            helper(root.right,sum-root.val,temp+[root.val])

        res = []
        helper(root,targetSum,[])
        return res

思路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: TreeNode, targetSum: int) -> List[List[int]]:
        # 利用栈进行迭代
        # 判断根节点是否为空节点
        if root == None:
            return []

        res = []
        tmp = []
        stack = [(root,targetSum,tmp)]

        while stack:
            # 出栈
            node,sum,tmp = stack.pop()
            # 当当前节点为叶子节点且剩余值等于叶子值
            if node.left == None and node.right == None and node.val == sum:
                tmp += [node.val]
                res.append(tmp)
            
            # 入栈
            if node.left != None:
                stack.append((node.left,sum-node.val,tmp+[node.val]))
            if node.right != None:
                stack.append((node.right,sum-node.val,tmp+[node.val]))
        
        return res

129. 求根节点到叶子节点数字之和

  这道题目相比112–路径总和,增加了两个变化:

  1. 每一个结点相当于位上的值。我们只需要每一层乘以10 加上自己的值就可以了。
  2. 所有路径需要累加起来。我们只需要在最后对结果列表进行求和即可。

给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。
每条从根节点到叶节点的路径都代表一个数字:
例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。
计算从根节点到叶节点生成的 所有数字之和
叶节点 是指没有子节点的节点。

示例:

输入:root = [4,9,0,5,1]
输出:1026
解释:
从根到叶子节点路径 4 -> 9 -> 5 代表数字 495
从根到叶子节点路径 4 -> 9 -> 1 代表数字 491
从根到叶子节点路径 4 -> 0 代表数字 40
因此,数字总和 = 495 + 491 + 40 = 1026

思路1:递归

# 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 sumNumbers(self, root: TreeNode) -> int:
        def helper(root,nums):
            if root == None:
                return root
            
            # 更新路径和
            nums *= 10
            nums += root.val

            # 如果当前节点是叶子节点,则将nums添加到res中
            if root.left == None and root.right == None:
                res.append(nums)

            # 递归调用左右子树
            if root.left != None:
                helper(root.left,nums)
            if root.right != None:
                helper(root.right,nums)

        res = []
        helper(root,0)   
        return sum(res)    

思路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 sumNumbers(self, root: TreeNode) -> int:
        # 判断根节点是否为空
        if root == None:
            return 0
        # 定义一个路径,保存节点与节点值
        stack = [(root,0)]
        # 保存路径
        res = []       
        while stack:
            node,nums = stack.pop()

            # 更新节点值
            nums *= 10
            nums += node.val
            # 判断当前节点是否是叶子节点,如果是,则保存路径
            if node.left == None and node.right == None:
                res.append(nums)

            # 如果当前节点非叶子节点,则将左右节点入栈
            if node.left != None:
                stack.append((node.left,nums))
            if node.right != None:
                stack.append((node.right,nums))
        return sum(res)

124. 二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42
在这里插入图片描述

思路:

可以参考官方题解二叉树中的最大路径和,写的很简洁
实现一个简化的函数 maxGain(node),该函数计算二叉树中的一个节点的最大贡献值
该函数的计算如下。

  1. 空节点的最大贡献值等于 0。
  2. 非空节点的最大贡献值等于节点值与其子节点中的最大贡献值之和(对于叶节点而言,最大贡献值等于节点值)。
    该函数的计算如下。

对根节点调用函数 maxGain,即可得到每个节点的最大贡献值。
根据函数 maxGain 得到每个节点的最大贡献值之后,如何得到二叉树的最大路径和?
对于二叉树中的一个节点,该节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值,如果子节点的最大贡献值为正,则计入该节点的最大路径和,否则不计入该节点的最大路径和。维护一个全局变量 maxSum 存储最大路径和,在递归过程中更新 maxSum 的值,最后得到的 maxSum 的值即为二叉树中的最大路径和。

# 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 __init__(self):
        self.maxSum = float('-inf')  # 用于保存最大路径和

    def maxPathSum(self, root: TreeNode) -> int:
        # 递归计算左右节点的最大贡献值
        def maxGain(node):
            # 如果节点为空,则贡献值为0
            if node == None:
                return 0

            # 递归计算左右子节点的最大贡献值
            # 只有在最大贡献值大于0时,才会选取对应子节点
            left_Gain = max(maxGain(node.left),0)
            right_Gain = max(maxGain(node.right),0)

            # 当前节点的最大路径和等于左子树的贡献值+父节点的值+右子树的贡献值
            priceNewPath = node.val + left_Gain + right_Gain

            # 更新最大值
            self.maxSum = max(self.maxSum,priceNewPath)

            # 返回节点的最大贡献值
            return node.val + max(left_Gain,right_Gain)
        maxGain(root)
        return self.maxSum

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径
说明: 叶子节点是指没有子节点的节点。

示例:
在这里插入图片描述
思路:迭代

我们维护一个队列,存储节点以及根到该节点的路径。一开始这个队列里只有根节点。在每一步迭代中,我们取出队列中的首节点,如果它是一个叶子节点,则将它对应的路径加入到答案中。如果它不是一个叶子节点,则将它的所有孩子节点加入到队列的末尾。当队列为空时,迭代结束。

# 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 binaryTreePaths(self, root: TreeNode) -> List[str]:
        # 判断根节点是否为空
        if root == None:
            return root
        
        # 定义队列来保存节点与路径
        queue = [(root,'')]
        # 用于保存结果
        res = []
        while queue:
            size = len(queue)
            for _ in range(size):
                node,tmp = queue.pop(0)
                tmp += str(node.val)
                # 如果当前节点为叶子节点,记录路径
                if node.left == None and node.right == None:
                    res.append(tmp)

                # 格式要求
                tmp += '->'
                # 如果当前节点非叶子节点,则添加入队
                if node.left != None:
                    queue.append((node.left,tmp))
                if node.right != None:
                    queue.append((node.right,tmp))
        
        return 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 binaryTreePaths(self, root: TreeNode) -> List[str]:
        # 判断根节点是否为空
        if root == None:
            return root
        
        # 定义栈来保存节点与路径
        stack = [(root,'')]
        # 用于保存结果
        res = []
        while stack:
            node,tmp = stack.pop(0)
            tmp += str(node.val)
            # 如果当前节点为叶子节点,记录路径
            if node.left == None and node.right == None:
                res.append(tmp)

            # 格式要求
            tmp += '->'
            # 如果当前节点非叶子节点,则添加入队
            if node.left != None:
                stack.append((node.left,tmp))
            if node.right != None:
                stack.append((node.right,tmp))
        
        return res

如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!
在这里插入图片描述


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

leetcode—21.二叉树路径和相关题目leetcode总结 的相关文章

  • linux 新建用户、用户组 以及为新用户分配权限

    一 Linux系统用户账号的管理 用户账号的管理工作主要涉及到用户账号的添加 修改和删除 添加用户账号就是在系统中创建一个新账号 然后为新账号分配用户号 用户组 主目录和登录Shell等资源 刚添加的账号是被锁定的 无法使用 1 添加新的用
  • C++性能优化系列——矩阵转置(八)IPP转置API性能测试

    本篇记录Intel 高性能计算函数库IPP中的转置函数ippiTranspose 8u C1R的执行情况 方便性能优化系列篇中转置实现做性能对比 函数说明 解释来自IPP2018发布文档 Intel Integrated Performan

随机推荐

  • Linux报错:-bash: 路径xx: No such file or directory解决方法

    为什么80 的码农都做不了架构师 gt gt gt 问题 出现这个错误 bash 路径xx No such file or directory除了cd能用外 所有linux命令都不能用 一般导致问题原因是etc profile配置文件出错导
  • 有趣的Hack-A-Sat黑掉卫星挑战赛——被破坏的阿波罗计算机(解法一)

    国家太空安全是国家安全在空间领域的表现 随着太空技术在政治 经济 军事 文化等各个领域的应用不断增加 太空已经成为国家赖以生存与发展的命脉之一 凝聚着巨大的国家利益 太空安全的重要性日益凸显 1 而在信息化时代 太空安全与信息安全紧密地结合
  • 【linux学习记笔】以war包安装部署Jenkins

    Jenkins的安装方法很多 这篇文章记录了个人学习使用war方式安装方式 一 安装准备 安装之前要先配置好JDK 配置方法在这里就不详细说明了 二 进入Jenkins官网下载war包 Jenkins官网 https www jenkins
  • 使用百度地图API出错

    在使用百度地图API做地理定位的时候 从拾取坐标系系统获取的坐标 其经纬度是反的 所以直接复制过去的时候 显示不出来地图的全景图 使用时记得交换位置
  • c#用Gnuplot画图源码

    直接调用这个类即可 需要下载个GnuPlot安装下 Author Leonardo Tazzini using System using System Diagnostics using System Drawing using Syste
  • Python爬虫学了几个月却不敢接单?过来人的经验总结收好!

    前几天有刷到一个提问 爬虫学了几个月了却还是不敢上手去接单 爬虫接单靠不靠谱 有些新手心里会犯嘀咕 怕不小心就踩了红线 作为过来人也接过不少单 来浅聊一下我的经验 这篇所说的经验总结可能更适合爬虫新手 爬虫大佬可以忽略 此篇小结 Pytho
  • MHA高可用配置和故障切换

    目录 引言 一 MySQL四种同步方式 1 1 异步复制 Async Replication 1 2 同步复制 Sync Replication 1 3 半同步复制 Semi Sync Replication 1 4 增强半同步复制 los
  • 锂电池保护板电路分析

    锂电池保护板基本模型如下 P 和P 接到负载以及充电电路 T接到充电电路的NTC R1 基准供电电阻 C1 起瞬间稳压和滤波作用 R2 过流 短路检测 R3 NTC电阻 1 当电路正常工作的的时候CO DO都是高电平 U2的两个NMOS导通
  • QT超市管理系统

    QT超市管理系统 前言 QT介绍 pro文件 主文件 main函数 窗口函数 mainwindow 用户登录 user login 超市系统数据库 maketsql 超市商品的增删改查 dlg addmak 收款码界面 picture 结语
  • SpringBoot中Server层以及Mapper层常用注解

    最近看了一下SpringBoot2的课程 发现好多的注解并不是很了解 只是简单的会用 但是真是发生的作用却不知道 最近花了一些时间把这些注解进行了一下整理 针对不同的层级进行了细致的划分 最近几天会依次给大家更新关于注解的内容 对大家有帮助
  • 大带宽、高速率接口对比---USB、PCIE、SATA、HDMI和以太网等接口

    一 PCIE接口 二 USB接口 三 SATA接口 SATA 编码方式 原始频宽 传输速率 有效速率 排线最长长度 SATA1 0 SATA2 0 8bit 10bit 3Gb s 300MB s 275MB s 1M SATA3 0 8b
  • VMware Workstation 15 语言修改

    VMware Workstation 15 语言修改 Win10系统之前因为2345 Flash的原因 把系统的地区改成了中国以外的地区 后来发现不仅Flash的问题没解决 VMware虚拟机的中文界面显示也变成了英文 之后在论坛里看到一个
  • win10如何把繁体字改成简体字

    win10如何把繁体字改成简体字 WBOY 发布 2023 07 09 13 17 05 转载 3431人浏览过 win10客户在开展文字输入的时候遇到了字体变为繁体字的状况 那么如何把繁体字改成简体字呢 是否有快捷键呢 win10繁体字改
  • Elasticsearch 相关度评分算法

    Elasticsearch 相关度评分算法 一 相关度评分算法的组成 1 1 boolean model 1 2 TF IDF 1 3 Vector space model 二 Lucene中的相关度分数算法 三 优化相关度分数计算的方式
  • QT设置控件颜色

    转自 http hi baidu com xiaofan812 item 9a039d62849fa22268105b11 一般的属于QWidget子类的一些控件 可以直接使用样式表 例如 label gt setStyleSheet co
  • 第二章 Vue 核心技术

    2 1 Vue 入门开发 2 1 1 创建工程 在本地创建文件夹D Project vue WebStudy 打开 VS Code 点击 File gt Open Folder 找到 D Project vue WebStudy 打开 单击
  • 使用Lattice包进行基础绘图 - R语言

    使用Lattice包进行基础绘图 R语言 Lattice包是R语言中一个强大且灵活的绘图工具 它可以用于创建各种类型的统计图形 在本文中 我们将介绍如何使用Lattice包进行基础绘图 并提供相应的源代码示例 首先 我们需要安装并加载Lat
  • javascript编写自己的模板解析器

    编写自己的模板解析器 因为最近在研究artTemplate ejs baaiduTemplate等模板 所以 一时兴起 自己也写了个简单的模板解析器 一个最基本的模板解析器 需要有什么功能呢 读取变量值 解析模板语句 按照这个思路 我们编写
  • 简单的感知器实现

    什么是感知器 神经网络的组成单元 神经元 神经元也叫感知器 感知器的组成 输入权值 激活函数 输出 感知器的输出公式 y f w x b 下面构建一个简单的感知器 from functools import reduce 1 functoo
  • leetcode—21.二叉树路径和相关题目leetcode总结

    文章目录 引言 112 路径总和 113 路径总和 II 129 求根节点到叶子节点数字之和 124 二叉树中的最大路径和 257 二叉树的所有路径 引言 树的求和属于树的题目中比较常见的 因为可以有几种变体 灵活度比较高 也可以考察到对于