算法挑战52: 节点与其祖先之间的最大差值

9 阅读2分钟

题目:

给定二叉树的根节点 root,找出存在于 不同 节点 A 和 B 之间的最大值 V,其中 V = |A.val - B.val|,且 A 是 B 的祖先。

(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)

思路:

我真神了, 竟然想到了 -- 只需计算当前节点与最大值和最小的的差的绝对值

不过我还是没过, 因为我搞了个全局的max和min

这样就会导致遍历到右子树时, 会与左子树的节点值进行计算

这是不应该的

于是,应该用参数传递max和min进去

这里有一个疑惑的点, 就是传参会复制一份值,左子树改变了,右子树不会收到影响

让我们看看你认可的那个“前序遍历”代码是怎么跑的:

javascript

编辑

function dfs(node, maxVal, minVal) {
    // ...
    let newMax = Math.max(maxVal, node.val);
    let newMin = Math.min(minVal, node.val);
    
    // 关键点在这里 👇
    dfs(node.left, newMax, newMin);  // 调用 1
    dfs(node.right, newMax, newMin); // 调用 2
}

假设根节点是 8,左孩子是 3,右孩子是 10。

  1. 根节点 (8)

    • 算出 newMax = 8newMin = 8
    • 执行 调用 1:把数字 8 和 8 传给左孩子。
    • 执行 调用 2:把数字 8 和 8 传给右孩子。
  2. 左孩子 (3)

    • 它收到的参数是 8, 8。
    • 它算出 newMax = 8newMin = 3
    • 它继续往下传...
    • 注意:哪怕左孩子把 newMin 改成了 3,甚至改成了 100,这跟右孩子有什么关系呢?
  3. 右孩子 (10)

    • 它收到的参数依然是根节点给的 8, 8。它根本不知道左孩子那边发生了什么。

代码:

var maxAncestorDiff = function (root) {
    //每个节点只需要和自己的子树中的最大值和最小值进行计算
    let res = 0;
    function dfs(root, max, min) {
        if (!root) return;

        //计算
        let sum = Math.max(res, Math.abs(root.val - min), Math.abs(root.val - max));
        res = sum > res ? sum : res;
        //添加上当前节点,看看最大值和最小值变化没
        let newMax = Math.max(max, root.val);
        let newMin = Math.min(min, root.val);

        dfs(root.left, newMax, newMin);
        dfs(root.right, newMax, newMin);
    }
    dfs(root, root.val, root.val);

    return res;
};