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

LeetCode 2246代码疑问:交换Math.max参数顺序为何结果不同?

LeetCode 2246题:最长相邻字符不同路径问题排查

问题背景

我在解决LeetCode 2246. Longest Path With Different Adjacent Characters问题,题目要求如下:

给定一棵以节点0为根的树(无环连通无向图),包含n个编号从0到n-1的节点。树由大小为n的0索引数组parent表示,其中parent[i]是节点i的父节点。节点0是根节点,故parent[0] == -1。
同时给定长度为n的字符串s,s[i]是分配给节点i的字符。
返回树中最长路径的长度,要求路径上相邻节点的字符均不相同。

我的代码实现如下:

function longestPath(parent: number[], s: string): number {
  const childrenMap: Record<number, number[]> = {}
  for (let node = 0; node < parent.length; node++) {
    const parentNode = parent[node]
    childrenMap[parentNode] = childrenMap[parentNode] ?? []
    childrenMap[parentNode].push(node)
  }
  let max = 0
  const dfs = (node = 0, parentNode = -1): number => {
    if (s[node] === s[parentNode]) {
      max = Math.max(max, dfs(node, -1))
      return 0
    }

    const [a = 0, b = 0] = (childrenMap[node] ?? []).map((child) => dfs(child, node))
      .sort((la, lb) => lb - la)
    max = Math.max(max, 1 + a + b)
    return a + 1
  }
  dfs()
  return max
}

console.log(
  longestPath(
    [-1, 56, 10, 79, 52, 0, 37, 39, 127, 125, 116, 52, 95, 131, 105, 55, 55, 52, 87, 35, 43, 130, 87, 103, 8, 73, 8, 116, 4, 43, 60, 104, 116, 118, 78, 9, 133, 139, 7, 127, 96, 28, 52, 79, 78, 36, 102, 134, 100, 104, 47, 127, 129, 77, 121, 133, 10, 58, 104, 55, 69, 73, 107, 9, 139, 79, 52, 72, 130, 78, 112, 43, 14, 4, 120, 9, 139, 118, 52, 52, 73, 82, 79, 58, 121, 80, 139, 10, 25, 74, 10, 123, 134, 112, 40, 80, 108, 128, 5, 52, 43, 31, 10, 42, 79, 139, 86, 58, 3, 118, 117, 21, 4, 79, 45, 26, 5, 122, 102, 13, 88, 139, 108, 118, 116, 10, 58, 32, 80, 125, 121, 105, 116, 104, 82, 131, 39, 10, 126, 125],
    'vodpyvpjmogqvwnibqasbulkfbfugvtlpdtsmydrbrekavkhifoypepbcnzpmasbnlrfqgdhnmvhldsrogjsntummchcftzrnycichziopmphfqwqdsihoywdpqqkyvzrhbqorwrkmns',
  ),
)

这段代码输出结果为13,但预期输出是17。当我把代码中的:

max = Math.max(max, dfs(node, -1))

替换成:

max = Math.max(dfs(node, -1), max)

结果就正确了(输出17)。我看不出两者的区别,请问问题出在哪里?


问题原因分析

这两个写法看似等价,但核心差异在于函数调用的副作用执行时机。

Math.max(a, b)会严格按照参数顺序计算:先算第一个参数,再算第二个参数。而你的dfs(node, -1)函数带有副作用——它在执行过程中会直接修改全局变量max的值,这就是问题的关键。

  • 原写法Math.max(max, dfs(node, -1)):先读取当前max的旧值,再执行dfs函数(此时dfs内部会把max更新到更大的正确值),但Math.max用的是执行dfs之前的旧max和dfs的返回值比较,最后把比较结果赋值给max,这会直接覆盖dfs内部刚更新的正确max值。
  • 修改后的写法Math.max(dfs(node, -1), max):先执行dfs函数,此时dfs会先把max更新到正确的更大值,再读取更新后的max值和dfs的返回值比较,最终max会保留两者中的较大值,不会覆盖之前的正确更新。

举个简单的场景举例:假设当前max是10,dfs(node, -1)执行时会把max改成17,同时返回5。

  • 原写法:先拿旧max10,和返回值5比较,取10赋值给max,导致max又变回10,覆盖了dfs内部更新的17。
  • 修改后:先执行dfs让max变成17,再拿返回值5和17比较,取17赋值给max,最终max保留了正确的17。

本质上,你的dfs函数同时承担了两个职责:返回当前节点的最长单链长度,以及更新全局的最长路径max。这种带有副作用的函数调用顺序,直接影响了最终的max结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:09:24