Golang递归函数中变量声明位置不同导致left值异常的原因?
问题分析:Go递归中变量声明位置的差异
两种写法的核心差异
外层声明变量(闭包共享)
你在diameterOfBinaryTree函数外层声明的left、right是所有递归调用共享的闭包变量,每一层dfs的执行都会直接修改这两个变量的唯一实例。递归过程中,上层节点需要的左/右子树深度会被后续深层或分支的递归调用覆盖,导致变量值完全不符合预期。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
相关产品推荐
相关产品推荐

