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
相关产品推荐
相关产品推荐

