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

1026. 节点与其祖先之间的最大差值

关键词:图论、深度优先

题目来源:1026. 节点与其祖先之间的最大差值 - 力扣(Leetcode)

题目描述

T图论
T深度优先

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

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

输入:root = [8,3,10,1,6,null,14,null,null,4,7,13]
输出:7

输入:root = [1,null,2,null,0,3]
输出:3
数据范围
树中的节点数在 2 到 5000 之间。
0 <= Node.val <= 105

问题分析

此类问题,朴素的想法就是,找到一种遍历策略,将所有可能的情况全枚举一遍。在本问题中就是,求出每个结点与其所有祖先的距离的最大值。

设点对(x, y),其中x是y的祖先,其构成的值为|x-y|,去掉绝对值,要么是(x-y),要么是(y-x)

  • 对于(x-y),若y的祖先中还有比x更大的结点,显然(x-y)就不是y到其所有祖先的距离的最大值
  • 对于(y-x),若y的祖先中还有比x更小的结点,显然(y-x)就不是y到其所有祖先的距离的最大值

于是,我们发现,结点y到与其所有祖先的距离的最大值必然会在abs(y-minV)和abs(y-maxV)中产生。

于是,在计算y前,只需要知道y祖先结点的最大值和最小值即可,这正符合深度优先遍历的特点。

时间复杂度:O(n)

空间复杂度:O(n)

代码实现

int dfs(TreeNode *u, int minV, int maxV) {
    if (!u)return 0;
    // 求当前结点与其祖先结点的最大差值
    int dis = max(abs(u->val - minV), abs(u->val - maxV));
    // 求u的左右孩子的祖先结点的最小值和最大值
    minV = min(u->val, minV), maxV = max(u->val, maxV);
    // 求左右子树中的结点与其各自祖先结点的最大差值
    dis = max(dfs(u->left, minV, maxV), dis);
    dis = max(dfs(u->right, minV, maxV), dis);
    // 每个结点与其祖先结点的最大差值
    return dis;
}

int maxAncestorDiff(TreeNode *root) {
    return dfs(root, root->val, root->val);
}
posted @ 2023-04-18 15:48  字节幺零二四  阅读(25)  评论(0)    收藏  举报