输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

解题思路:

本问题是典型的二叉树方案搜索问题,使用回溯法解决,其包含 先序遍历 + 路径记录 两部分。

先序遍历: 按照 “根、左、右” 的顺序,遍历树的所有节点。
路径记录: 在先序遍历中,记录从根节点到当前节点的路径。当路径为 ① 根节点到叶节点形成的路径 且 ② 各节点值的和等于目标值 sum 时,将此路径加入结果列表。

算法流程:
pathSum(root, sum) 函数:

初始化: 结果列表 res ,路径列表 path 。
返回值: 返回 res 即可。
recur(root, tar) 函数:

递推参数: 当前节点 root ,当前目标值 tar 。
终止条件: 若节点 root 为空,则直接返回。
递推工作:
路径更新: 将当前节点值 root.val 加入路径 path ;
目标值更新: tar = tar - root.val(即目标值 tar 从 sum 减至 00 );
路径记录: 当 ① root 为叶节点 且 ② 路径和等于目标值 ,则将此路径 path 加入 res 。
先序遍历: 递归左 / 右子节点。
路径恢复: 向上回溯前,需要将当前节点从路径 path 中删除,即执行 path.pop() 。

复杂度分析:
时间复杂度 O(N) : N 为二叉树的节点数,先序遍历需要遍历所有节点。
空间复杂度 O(N) : 最差情况下,即树退化为链表时,path 存储所有树节点,使用 O(N)额外空间。
代码:
值得注意的是,记录路径时若直接执行 res.append(path) ,则是将 path 对象加入了 res ;后续 path 改变时, res 中的 path 对象也会随之改变。

正确做法:res.append(list(path)) ,相当于复制了一个 path 并加入到 res 。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution:def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:res, path = [], []# 先序遍历:根左右def recur(root, target):if not root:returnpath.append(root.val)target -= root.val# 找到路径if target == 0 and not root.left and not root.right:res.append(list(path))  # 复制了一个 path 加入到 res 中,这样修改 path 不影响 resrecur(root.left, target)recur(root.right, target)# 向上回溯,需要删除当前节点path.pop()recur(root, sum)return res

深度优先搜索。使用前序遍历,使用两个全局变量result和tmp,result来存放最终结果,tmp用来存放临时结果。

每次遍历,我们先把root的值压入tmp,然后判断当前root是否同时满足:

  • 与给定数值相减为0;
  • 左子树为空;
  • 右子树为空。

如果满足条件,就将tmp压入result中,否则,依次遍历左右子树。需要注意的是,遍历左右子树的时候,全局变量tmp是不清空的,直到到了根结点才请空tmp。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:# 返回二维列表,内部每个列表表示找到的路径def FindPath(self, root, expectNumber):# write code hereif not root:return []if not root.left and not root.right and expectNumber == root.val:return [[root.val]]res = []left = self.FindPath(root.left, expectNumber-root.val)right = self.FindPath(root.right, expectNumber-root.val)for i in left+right:res.append([root.val]+i)return res

在做这一题之前,我们先来看看怎么输出二叉树的从根结点到每个叶子节点的路径。

# 递归解法
class TreeNode:def __init__(self, value):self.val = valueself.left = Noneself.right = Noneclass Solution:def binaryTreePaths(self, root):if root == None:return []result = []self.DFS(root, result, [root.val])return resultdef DFS(self, root, result, path):if root.left == None and root.right == None:result.append(path)if root.left != None:self.DFS(root.left, result, path + [root.left.val])if root.right != None:self.DFS(root.right, result, path + [root.right.val])
# 非递归解法class TreeNode:def __init__(self, value):self.val = valueself.left = Noneself.right = Noneclass Solution2:def binaryTreePaths2(self, root):if root == None:return []result = []stack = []stack.append((root, [root.val]))while stack:node, path = stack.pop()if node.left == None and node.right == None:result.append(path)if node.left != None:stack.append((node.left, path + [node.left.val]))if node.right != None:stack.append((node.right, path + [node.right.val]))return result

现在再来看这一题,就会发现:其实这一题就是引出所有的从根结点到叶子结点的路径的变形,就在判断条件上多了一个 sum(path) == self.sums。所以,解法如下:

# 方法一:递归
class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:# 返回二维列表,内部每个列表表示找到的路径def FindPath(self, root, expectNumber):# write code hereresult = []if root == None:return resultself.sums = expectNumberself.DFS(root, result, [root.val])return resultdef DFS(self, root, result, path):if root.left == None and root.right == None and sum(path) == self.sums:result.append(path)if root.left != None:self.DFS(root.left, result, path + [root.left.val])if root.right != None:self.DFS(root.right, result, path + [root.right.val])
# 方法二:非递归
class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:# 返回二维列表,内部每个列表表示找到的路径def FindPath(self, root, expectNumber):# write code hereif root == None:return []result = []stack = []stack.append((root, [root.val]))while stack:node, path = stack.pop()if node.left == None and node.right == None and sum(path) == expectNumber:result.append(path)if node.right != None:stack.append((node.right, path + [node.right.val]))if node.left != None:stack.append((node.left, path + [node.left.val]))return result

[二叉树]二叉树中和为某一值的路径 (剑指offer24)相关推荐

  1. 剑指offer:面试题34. 二叉树中和为某一值的路径

    题目:二叉树中和为某一值的路径 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径. 示例: 给定如下二叉树,以及目标和  ...

  2. 《剑指offer》— JavaScript(24)二叉树中和为某一值的路径

    二叉树中和为某一值的路径 题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 思路 前序遍历二叉树, ...

  3. 《剑指offer》-- 从上往下打印二叉树、二叉搜素树的后序遍历、二叉树中和为某一值的路径、二叉树与双向链表

    一.从上往下打印二叉树: 1.题目: 上往下打印出二叉树的每个节点,同层节点从左至右打印. 2.解题思路: 用arraylist模拟一个队列来存储相应的TreeNode. 3.代码实现: public ...

  4. 剑指 Offer 34. 二叉树中和为某一值的路径【附完整可运行代码】

    立志用最少的代码做最高效的表达 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径. 示例: 给定如下二叉树,以及目标和 ...

  5. C#刷剑指Offer | 二叉树中和为某一值的路径

    [C#刷题]| 作者 / Edison Zhou 这是EdisonTalk的第292篇原创内容 我们来用之前学到的数据结构知识来刷<剑指Offer>的一些核心题目(精选了其中30+道题目) ...

  6. 数据结构与算法-- 二叉树中和为某一值的路径

    二叉树中和为某一值的路径 题目:输入一颗二叉树和一个整数,打印出二叉树中节点值的和为给定值的所有路径.从树的根节点开始往下一只到叶子节点所经过的节点形成一条路径. 我们用二叉树节点的定义沿用之前文章中 ...

  7. 【LeetCode】剑指 Offer 34. 二叉树中和为某一值的路径

    [LeetCode]剑指 Offer 34. 二叉树中和为某一值的路径 文章目录 [LeetCode]剑指 Offer 34. 二叉树中和为某一值的路径 package offer;import ja ...

  8. 【重点】剑指offer——面试题25:二叉树中和为某一值的路径

    剑指offer--面试题25:二叉树中和为某一值的路径 参考网址:https://www.nowcoder.com/profile/5488508/codeBookDetail?submissionI ...

  9. 【LRD,DLR】BST的后续遍历序列,二叉树中和为某一值的路径

    D是Degree,后续遍历就是LRD,前序遍历就是DLR. 面试题33:BST的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false. ...

最新文章

  1. 3、循序渐进设计模式-创建型
  2. 【Linux入门到精通系列讲解】VFS分区动态绑定和CentOS7分区类型
  3. some understanding of《Improved Use of Continuous Attributes in C4.5》
  4. Windows Phone 7 Bitmap编码
  5. 读书笔记 --- [基础知识点] 小结3
  6. 小学生都能看懂的FFT!!!
  7. zabbix网络发现主机
  8. Outlook怎么打印日历 Outlook日历打印教程
  9. php时间转两位数年份,PHP常用时间函数资料整理
  10. 《天天数学》连载16:一月十六日
  11. 关于OpenGL ES中的纹理压缩
  12. 使用计算机键盘的基本步骤,键盘指法练习方法
  13. 2021年9月电子学会Python等级考试试卷(四级)考题解析
  14. 随机数公式生成一个负数和正数之间的数_随机生成数据的公式 如何在EXCEL随机生成数字,要正负的。...
  15. P7369 [COCI2018-2019#4] Elder 题解
  16. java线程(Thread)的创建与常用方法
  17. workflow的简介
  18. 亚马逊裁员9000人、OpenAI估值已达290亿美元、首例涉虚拟数字人侵权案
  19. Java小农养成记第三十天
  20. ppt转换器免费下载在哪儿

热门文章

  1. python如何自动打印_利用Python每天自动打印练习题
  2. 性能优化(数据库设计原则)
  3. 使用SpringBoot Admin监控SpringCloud微服务
  4. XXX集团财务决策支持系统——财务分析指标(系列五)
  5. Spring思维导图(IOC篇)
  6. 给定任意字符串,计算一共能组合成多少个单词bing
  7. 设计模式系列之单例模式(java)
  8. java 如何知道对象是否被修改过_Java 并发编程:AQS 的原子性如何保证
  9. laravel中的数据迁移表结构、字段类型、定义整理
  10. xstream不映射字段_这本XStream学习手册,真的不来看看?