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

递归参数传递机制与targetSum手动回溯必要性的技术咨询

递归参数传递与回溯的本质

一、Java参数传递的核心规则

Java的参数传递是严格的值传递,分两种情况:

  • 基本数据类型(int、double等):传递的是变量值的副本。方法内部对参数的修改只会作用于副本,不会影响原变量的值。
  • 引用数据类型(对象、数组等):传递的是对象引用地址的副本。方法内部通过引用修改对象的内容时,会影响原对象;但修改引用本身(比如把参数指向新对象)不会影响原引用。

二、第一个例子:无需手动回溯的原因

在hasPathSum问题中,递归调用传递的是targetSum - root.val这个计算后的新值:

return hasPathSum(root.left, targetSum - root.val) 
        || hasPathSum(root.right, targetSum - root.val);
  • 每次递归都会创建一个新的targetSum副本,子递归层的操作完全独立于当前层的targetSum变量。
  • 当子递归返回时,当前层的targetSum仍然是调用前的原始值,状态自然正确,不需要手动恢复。

三、第二个例子:手动回溯是多余的(附正确场景)

你提供的pathSum的dfs方法中,targetSum += node.val属于不必要的手动回溯,原因如下:

targetSum -= node.val;
dfs(node.left, targetSum);
dfs(node.right, targetSum);
targetSum += node.val; // 这一步是多余的
  • targetSum是基本类型的局部变量,修改后传递给子递归的是值的副本,子递归的操作不会影响当前层的targetSum。
  • 子递归返回后,当前层的targetSum并没有被修改,所以不需要恢复。

真正需要手动回溯的场景

只有当使用引用类型变量跟踪状态时,才需要手动回溯。比如用List记录路径(引用类型):

private void dfs(TreeNode node, int targetSum, List<Integer> path) {
    if (node == null) return;
    path.add(node.val); // 修改引用类型的内容
    // 统计以当前节点结尾的符合条件的路径
    int sum = 0;
    for (int i = path.size() - 1; i >= 0; i--) {
        sum += path.get(i);
        if (sum == targetSum) count++;
    }
    dfs(node.left, targetSum, path);
    dfs(node.right, targetSum, path);
    path.remove(path.size() - 1); // 必须手动回溯,恢复path的原始状态
}

这里path是引用类型,子递归会共享同一个List对象。如果不回溯,处理右子树时,左子树的节点还留在path中,会导致路径统计错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:45:00