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

Golang递归函数中变量声明位置不同导致left值异常的原因?

问题分析:Go递归中变量声明位置的差异

两种写法的核心差异

  1. 外层声明变量(闭包共享)
    你在diameterOfBinaryTree函数外层声明的left、right是所有递归调用共享的闭包变量,每一层dfs的执行都会直接修改这两个变量的唯一实例。递归过程中,上层节点需要的左/右子树深度会被后续深层或分支的递归调用覆盖,导致变量值完全不符合预期。

  2. dfs内部用:=声明变量
    这种写法里的left、right是每个递归栈帧的局部变量,每个dfs调用都拥有独立的变量副本,互不干扰。当前节点的左子树递归返回值会存在专属的left里,右子树返回值存在专属的right里,不会被其他递归调用的操作影响。

为什么外层声明会导致left始终为-1

假设你初始给left赋值为-1,递归过程中:

  • 当处理左子树的深层节点时,left会被赋值为该节点左子树的深度(比如nil节点返回0),但后续处理右子树或回溯到上层节点时,其他dfs调用会再次修改left的值。
  • 如果你的递归逻辑中,某些路径下left的赋值被后续递归覆盖,甚至存在分支没走到赋值逻辑,最终回到最外层时,left可能保留初始的-1,或是被重置为某个非预期的临时值。本质是共享变量无法保存每个递归节点的独立状态,导致值被污染。

举个简化的错误写法示例:

func diameterOfBinaryTree(root *TreeNode) int {
    var left, right int = -1, -1
    var dfs func(*TreeNode) int
    dfs = func(node *TreeNode) int {
        if node == nil {
            return 0
        }
        // 所有递归调用都修改同一个left、right
        left = dfs(node.Left)
        right = dfs(node.Right)
        return max(left, right) + 1
    }
    dfs(root)
    return left + right
}

这里处理右子树时,left会被右子树的dfs调用修改,导致根节点的left不再是左子树的深度,而是右子树中某个节点的左子树深度,结果完全错误。

而正确的写法:

func diameterOfBinaryTree(root *TreeNode) int {
    maxDia := 0
    var dfs func(*TreeNode) int
    dfs = func(node *TreeNode) int {
        if node == nil {
            return 0
        }
        // 每个递归调用都有自己的left、right
        left := dfs(node.Left)
        right := dfs(node.Right)
        maxDia = max(maxDia, left+right)
        return max(left, right) + 1
    }
    dfs(root)
    return maxDia
}

这里每个dfs调用的left和right都是独立的,能正确记录当前节点的左右子树深度,进而计算出正确的直径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:37:06