查找二叉树中指定节点的路径 (Python)

2024-01-12

我在计算二叉树中从根到指定节点的路径时遇到问题(这是专门针对此问题的 Python 解决方案)。

这是一个例子。给定下面的二叉树,如果我指定值为 4 的节点,我想返回 [1, 2, 4]。如果我指定值为5的节点,我想返回[1,2,5]。

       1
     /  \
   2      3
 /  \
4    5

这是我尝试的解决方案。

class TreeNode:
 def __init__(self, x):
     self.val = x
     self.left = None
     self.right = None

def path(root, k, l=[]):
    if not root:
        return []
    if root.val == k:
        return l

    # Pre-order traversal: Visit root, then left, then right.
    l.append(root.val)
    path(root.left, k, l)
    path(root.right, k, l)
    return l

现在如果我运行这个

>>> a = TreeNode(1)
>>> b = TreeNode(2)
>>> c = TreeNode(3)
>>> d = TreeNode(4)
>>> e = TreeNode(5)
>>> a.left = b
>>> a.right = c
>>> b.left = d
>>> b.right = e
>>> path(a, 4) # should be [1, 2, 4]
[1, 2, 5, 3]

你可以看到我没有达到预期。我确信这与我的遍历算法有关,但我不知道我哪里出了问题。任何帮助是极大的赞赏。


失踪者4是由于您从未附加它而引起的。在您的成功案例中:

if root.val == k:
    return l

...你需要这样做:

if root.val == k:
    l.append(root.val)
    return l

额外的3 and 5是因为你always附加中间情况下的值,即使对于要回溯的节点也是如此。

您可以通过仅在任一递归调用返回非空列表时附加它来解决此问题,但当然您的节点会乱序。最简单的解决方法是故意地使节点乱序:

# Pre-order traversal: Visit root, then left, then right.
if path(root.left, k, l) or path(root.right, k, l):
    l.append(root.val)

…然后在末尾反转列表,例如在包装函数中:

def path2(root, k):
    return list(reversed(path(root, k)))

但是,您的代码中仍然存在一个问题,就在这里:

def path(root, k, l=[]):

That []这是默认值l被创建一次,当def被执行,然后在每次调用时重用。这意味着path2(a, 4)会第一时间返回正确答案,[1, 2, 4],但是当您第二次调用它时,它会继续附加到同一个列表并返回[1, 2, 4, 1, 2, 4].

有几种惯用的方法可以解决这个问题,但在我们的例子中,因为我们已经在使用它path2包装函数,我们不妨在那里修复它:

def path2(root, k):
    return list(reversed(path(root, k, [])))

…然后去掉默认值path.


但是,您可能需要考虑从更容易理解的版本开始:

def path(root, k):
    if not root:
        return []
    if root.val == k:
        return [root.val]
    res = path(root.left, k)
    if res:
        return [root.val] + res
    res = path(root.right, k)
    if res:
        return [root.val] + res
    return []

(你可以把它写得短一点;我竭尽全力让这里的一切都变得明确。)

对于许多递归问题,反转它们并传递累加器是一项重要的优化,因为尾部调用消除可以从堆栈中删除一个分支。尽管 Python 不支持 TCE,但它still值得学习如何以尾部调用的方式做事,只是为了您自己的理解(当然,如果您用另一种语言编写代码)。但首先要学习如何做更简单的版本,然后才尝试反转它。

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

查找二叉树中指定节点的路径 (Python) 的相关文章

随机推荐

  • 更有效地从 Jar 中提取文件

    我正在扩展一个实用程序类 该类捆绑了一组图像和 xml 描述文件 目前 我将所有文件保存在一个目录中并从那里加载它们 该目录如下所示 8 png 8 xml 9 png 9 xml 10 png 10 xml 50 png 50 xml 这
  • 使用 mongo 同时拉取和添加设置

    我有一个集合 其中的元素可以简化为 tags 1 5 8 其中数组中至少有一个元素 并且所有元素都应该不同 我想用一个标签替换另一个标签 我认为不会有问题 所以我提出了以下查询 db colll update tags 1 pull tag
  • 使用 @font-face 会减慢加载时间。我可以强制客户端缓存字体吗?

    Update 看起来标头请求信息是罪魁祸首 如何更改请求标头的 max age 属性 TIA 您好 我在网站上使用 font face 并且遇到文本加载延迟的情况 可能是由于每页加载字体所致 我知道客户端必须下载一次字体才能正常显示 但是每
  • Chrome 分析器中的“未优化”警告是什么意思?

    当我使用 Chrome 中的开发人员工具收集 JavaScript CPU 配置文件时 我收到两个关于函数的神秘警告 未优化 优化次数过多 未优化 内联退出 这些实际上意味着什么 以及有哪些可能的解决方案 我见过的另一个是未优化 TryCa
  • 如何将 CallingMemberName 传递给自定义日志记录提供程序

    使用 ASP NET Core 并使用 ILogging 和 ILoggingProvider 实现我自己的控制台日志记录提供程序 因为我想将调用函数的名称作为日志记录以及日期 时间戳的一部分传递给记录器 检索调用函数名称的最佳方法是在函数
  • 同一java web应用程序的url重定向/映射到多个子域

    我有一个域名 例如 www domain com 我开发了一个java web应用程序 比如jwa 现在我想使用子域为不同的客户端安装相同的应用程序 最好的解决方案是什么 像 client1 domain com 之类的东西指向 clien
  • 支持 Phonegap 最小平台版本

    我的公司正在进行一个大项目 我必须开发 IOS Android symbian Windows Phone 和黑莓 在听说和研究 Phonegap 后 我真的正在考虑使用它 但是我想知道是否有以及哪些是针对这些平台使用 Phonegap 进
  • CanCan 和不带模型的控制器

    我正在使用 CanCan 进行授权 我在 app config ability rb 中定义了模型操作用户规则 并且工作正常 我已经添加了这一行load and authorize resource到我的 application contr
  • 如何在 Spark Streaming EC2 集群应用程序中从 S3 读取输入

    我试图让我的 Spark Streaming 应用程序从 S3 目录读取他的输入 但在使用 Spark submit 脚本启动它后我不断收到此异常 Exception in thread main java lang IllegalArgu
  • 如何使用 GattServer 以编程方式清除蓝牙缓存

    我对 BLE 有点熟悉 并且我面临着继承代码的一些问题 所以该应用程序的工作方式如下 启用 BLE 后 应用程序会扫描设备 该应用程序显示找到的设备 用户选择要配对的设备 该应用程序与设备配对 我面临的问题是 配对几次 情况有所不同 后 手
  • 为什么Python没有访问修饰符?Python中有什么替代品?

    为什么Python没有像C Java中那样的访问修饰符 即公共 私有等 Python中封装和信息隐藏的替代方法是什么 From 维基百科 https en wikipedia org wiki Python syntax and seman
  • AllAuth安装

    我正在尝试安装和配置 Django AllAuth 但遇到了很多障碍 恐怕我只是错过了一些可能会澄清一些事情的基本概念 为了使基本的社交身份验证正常工作 需要在社交提供商 Facebook Twitter 等 内部完成哪些设置 如果是这种情
  • 如何清除chrome应用程序的错误列表?

    首先介绍 Chrome 应用程序 我正在尝试简化某种工作流程 我已启用复选框来收集错误 但似乎无法在应用程序执行之间清除它们 我以为关闭应用程序然后重新启动它就可以了 现在唯一有效的方法是删除应用程序 然后重新加载包 要清除 收集错误 中的
  • 如何覆盖 Razor 的“名称”HtmlAttribute

    Html RadioButtonFor Model gt Model Location Location Html LabelFor Model gt Model Location Location Html RadioButtonFor
  • 在keras中,如何拟合不同类型的多个输入数据

    我有 3000 张 320 320 形状的图像 它们的拍摄时间以及它们的标签 现在我想使用这两种类型的数据 图像和时间 来预测它们的标签 主要代码如下 num classes 10 image out GlobalMaxPooling2D
  • Hibernate: LazyInitializationException: 未能延迟初始化角色集合。无法初始化代理 - 无会话

    我有下一个错误 nested exception is org hibernate LazyInitializationException failed to lazily initialize a collection of role c
  • 如何根据消息头属性仅读取特定队列消息

    我在 activemq 队列中有一个消息列表 每条消息都有一个带有值的自定义标头属性 我应该如何才能仅访问那些自定义标头属性值 123 的消息 我正在使用类似下面的东西从队列中选择消息 如何选择具有 customHeaderProperty
  • 如何处理android中的睡眠模式进入?

    我在任何地方都没有找到它 我该如何处理在android中进入睡眠模式 当Android设备进入睡眠模式时我想做什么 这是可能的还是有办法处理它 只需使用 BroadCastReceivers 进行系统调用 唤醒 睡眠 即可实现此目的 And
  • 如何在MVVM模式中实现INotifyPropertyChanged和observableCollection?

    我在模型中有一个 ObservableCollection of Products 我希望 ViewModel 能够侦听 ObservableCollection of Products 中的任何更改 我不确定如何去实施它 我读过一些教程
  • 查找二叉树中指定节点的路径 (Python)

    我在计算二叉树中从根到指定节点的路径时遇到问题 这是专门针对此问题的 Python 解决方案 这是一个例子 给定下面的二叉树 如果我指定值为 4 的节点 我想返回 1 2 4 如果我指定值为5的节点 我想返回 1 2 5 1 2 3 4 5