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

二叉树根到叶路径递归代码问题排查:为何路径被合并为一条?

问题分析与修复方案

你的这段递归代码出现「所有路径合并成一条」的问题,核心原因是复用了同一个List<Integer> l对象,且没有正确做回溯操作,具体问题点拆解如下:


1. 引用传递导致的路径污染

Java中集合是引用类型,当你执行lists.add(l)时,并没有把当前路径的副本存入lists,而是存入了l对象的引用。后续对l的所有修改(比如添加、删除元素)都会同步影响lists中已经保存的「路径」,最终所有条目指向的都是同一个不断被修改的列表。

2. 缺少回溯操作,路径节点无法回退

在递归访问左/右子树前,你执行了l.add(root.val),但递归返回后没有将这个节点从l中移除。这就导致左子树的路径节点会被带到右子树的路径中,不同分支的节点全部堆积在同一个列表里,最终变成一条包含所有节点的「大路径」。

3. 叶子节点处理逻辑冗余且错误

当遇到叶子节点时,你额外执行了l.add(root.val),但实际上如果统一在递归开头先添加当前节点,这里的重复添加会导致叶子节点被存入两次;同时直接把l加入lists的问题和第一条一致,还是引用传递的坑。


修正后的代码示例

下面是修复后的递归逻辑,解决了上述所有问题:

private void rec(TreeNode root, List<Integer> l, List<List<Integer>> lists) {
    if (root == null) return;
    
    // 1. 先将当前节点加入路径
    l.add(root.val);
    
    // 2. 处理叶子节点:创建当前路径的副本存入lists
    if (root.left == null && root.right == null) {
        lists.add(new ArrayList<>(l));
    } else {
        // 3. 递归访问左右子树
        rec(root.left, l, lists);
        rec(root.right, l, lists);
    }
    
    // 4. 回溯:移除当前节点,回到父节点的路径状态
    l.remove(l.size() - 1);
}

关键修复点说明:

  • 回溯操作:递归返回后执行l.remove(l.size() - 1),确保离开当前节点时,路径列表恢复到进入该节点前的状态,避免不同分支的节点互相干扰。
  • 副本存入:遇到叶子节点时,用new ArrayList<>(l)创建当前路径的副本,这样lists中保存的是独立的路径对象,后续修改l不会影响已保存的路径。
  • 统一节点添加逻辑:把当前节点的添加放在递归开头,避免叶子节点的重复添加,逻辑更简洁。

内容的提问来源于stack exchange,提问作者blanchey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:34:53