【LC每日一题】节点与其祖先之间的最大差值

39 阅读2分钟

题目描述:

给定二叉树的根节点 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 得出。

题目分析:

这道题目如果理解了题意,其实并不是很复杂,我们只需要了解这两个问题就可以有一个大概的解题方案:

  1. 在二叉树中,一个在第 n 层的树节点,他的祖先节点(一个节点的祖先节点包括从根节点到该节点路径上的所有节点)有几个?答案是 n 个。首先二叉树的层级(level) 是从根节点到某个节点的距离,根节点为第 0层,直接连接到根节点的节点位于第 1 层以此类推,那么在第一层的节点有一个祖先也就是根节点,第二层的节点有两个祖先,它的父节点和根节点。以下图为例,节点6的祖先节点为3和8

未命名文件 (3).png

  1. 求两个节点之间的差值,我们可以通过绝对值来求:比如 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;
};