题目描述:
给定二叉树的根节点 root
,找出存在于 不同 节点 A
和 B
之间的最大值 V
,其中 V = |A.val - B.val|
,且 A
是 B
的祖先。
(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)
输入:root = [8,3,10,1,6,null,14,null,null,4,7,13]
输出:7
解释:
我们有大量的节点与其祖先的差值,其中一些如下:
|8 - 3| = 5
|3 - 7| = 4
|8 - 1| = 7
|10 - 13| = 3
在所有可能的差值中,最大值 7 由 |8 - 1| = 7 得出。
题目分析:
这道题目如果理解了题意,其实并不是很复杂,我们只需要了解这两个问题就可以有一个大概的解题方案:
- 在二叉树中,一个在第
n
层的树节点,他的祖先节点(一个节点的祖先节点包括从根节点到该节点路径上的所有节点)有几个?答案是n
个。首先二叉树的层级(level) 是从根节点到某个节点的距离,根节点为第 0层,直接连接到根节点的节点位于第 1 层以此类推,那么在第一层的节点有一个祖先也就是根节点,第二层的节点有两个祖先,它的父节点和根节点。以下图为例,节点6的祖先节点为3和8
- 求两个节点之间的差值,我们可以通过绝对值来求:比如
diff = Math.abs(node1.val - node2.val)
解题方案:
当了解了这道题要求我们解决什么问题,最简单的方案则是,通过 DFS 枚举所有子节点,找出所有祖先节点,并计算差值,返回最大的差值即可。那么我们是否可以将“所有祖先”再进一步缩小范围, 我们只需要取 最小祖先的值 和 最大祖先的值即可举例来说,针对于上图中第三层节点 4
, 它的祖先节点有: 8, 3, 6
该节点的最大差值为 4
, 6
这个值显然是不需要参与计算的。我们可以在 dfs 的过程中将 最大值与最小值进行保留。
代码如下:使用从顶向下的dfs遍历,不断更新结果 res
var maxAncestorDiff = function(root) {
if (!root) return 0;
let res = 0;
const dfs = (tNode, minV, maxV) => {
if (!tNode) {
res = Math.max(res, maxV - minV);
return;
}
let maxVal = Math.max(maxV, tNode.val);
let minVal = Math.min(minV, tNode.val);
dfs(tNode.left, minVal, maxVal);
dfs(tNode.right, minVal, maxVal);
}
dfs(root, root.val, root.val);
return res;
};