You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归DFS实现二叉树根到目标节点路径打印的问题排查

问题分析与修复方案

你的代码之所以会让path包含所有遍历过的节点,核心问题出在默认参数陷阱、缺少回溯操作以及目标节点处理遗漏这几点上,具体分析和修复方案如下:

问题根源

  1. 可变默认参数的共享问题:Python中,像path=[]这种可变默认参数会在函数定义时初始化一次,所有函数调用都会共享同一个列表实例。这意味着多次调用dfs时,path会累积之前调用的结果。
  2. 未做回溯处理:当遍历左子树失败后,你没有把当前节点从path中移除,导致后续遍历右子树时,path里还保留着左子树遍历过的节点。
  3. 目标节点未加入路径:当找到目标节点时,你直接返回True,但没有将当前节点的val加入path,最终路径会缺失目标节点本身。
  4. 空节点处理无效:path = []只是给函数内的局部变量赋值,不会修改外部传入的path列表,完全起不到重置的作用。

修复方案(回溯法,空间效率高)

这是最常用的方式,通过回溯保证path始终只保留从根节点到当前遍历节点的路径:

def dfs(self, current, target, path=None):
    # 替换可变默认参数,每次调用无传入时新建空列表
    if path is None:
        path = []
    
    if current is None:
        return False
    
    # 先将当前节点加入路径
    path.append(current.val)
    
    # 找到目标节点,直接返回True,路径已包含当前节点
    if current.val == target.val:
        return True
    
    # 递归遍历左右子树,任一子树找到目标就返回True
    found = self.dfs(current.left, target, path) or self.dfs(current.right, target, path)
    
    if found:
        # 找到目标,保留当前路径
        return True
    else:
        # 未找到目标,回溯:移除当前节点
        path.pop()
        return False

修改说明

  • 把默认参数改为path=None,函数内部初始化空列表,彻底避免共享列表的问题。
  • 进入函数先将当前节点加入path,确保路径始终包含当前遍历的节点。
  • 左右子树遍历失败后,用path.pop()移除当前节点,实现回溯,保证path只保留有效路径。
  • 找到目标节点时直接返回True,此时path已经完整包含从根到目标的路径。

替代方案(传递新列表,无需回溯)

如果觉得回溯逻辑不好理解,可以每次递归时创建新的路径列表,这样左右子树的路径互不干扰:

def dfs(self, current, target, path=None):
    if path is None:
        path = []
    
    if current is None:
        return False
    
    # 创建新路径,不修改原路径
    new_path = path + [current.val]
    
    if current.val == target.val:
        # 找到目标,保存路径(可以用实例变量或返回值传递)
        self.target_path = new_path
        return True
    
    # 传递新路径递归遍历左右子树
    return self.dfs(current.left, target, new_path) or self.dfs(current.right, target, new_path)

这种方式不需要回溯,但每次递归都会复制列表,空间复杂度略高,适合小型二叉树场景。

内容的提问来源于stack exchange,提问作者Darth.Vader

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:17:56