LeetCode 1026. Maximum Difference Between Node and Ancestor【DFS,BFS,树】中等

news2024/10/7 6:46:43

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

Given the root of a binary tree, find the maximum value v for which there exist different nodes a and b where v = |a.val - b.val| and a is an ancestor of b.

A node a is an ancestor of b if either: any child of a is equal to b or any child of a is an ancestor of b.

Example 1:

Input: root = [8,3,10,1,6,null,14,null,null,4,7,13]
Output: 7
Explanation: We have various ancestor-node differences, some of which are given below :
|8 - 3| = 5
|3 - 7| = 4
|8 - 1| = 7
|10 - 13| = 3
Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7.

Example 2:

Input: root = [1,null,2,null,0,3]
Output: 3

Constraints:

  • The number of nodes in the tree is in the range [2, 5000].
  • 0 <= Node.val <= 105

题意:给定二叉树的根节点 root,找出存在于 不同 节点 A 和 B 之间的最大值 V,其中 V = |A.val - B.val|,且 A 是 B 的祖先。如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先。


解法 DFS自顶向下

如果节点 A A A 在从根节点到节点 B B B路径上,则称 A A A B B B祖先节点,称 B B B A A A子孙节点。

注:在这个定义中, B B B 的祖先节点可以是 B B B 自己。例如示例 1 中 6 6 6 的祖先节点自上而下依次为 8 , 3 , 6 8,3,6 8,3,6
注:虽然题目要求「不同节点」,但计算的是最大差值,相同节点算出来的差值为 0 0 0 ,不影响最大差值。

对于题目给出的公式 V = ∣ A . val − B . val ∣ V = |A.\textit{val} - B.\textit{val}| V=A.valB.val ,为了让 V V V 尽量大,分类讨论:

  • 如果 A . val < B . val A.\textit{val} < B.\textit{val} A.val<B.val ,那么 A . v a l A.val A.val 越小, V V V 越大。
  • 如果 A . v a l ≥ B . v a l A.val≥B.val A.valB.val ,那么 A . v a l A.val A.val 越大, V V V 越大;

因此,无需记录递归路径中的全部节点值,只需要记录递归路径中的最小值 m n mn mn 和最大值 m x mx mx 。每递归到一个节点 B B B ,计算
m a x ⁡ ( ∣ m n − B . v a l ∣ , ∣ m x − B . v a l ∣ ) max⁡(∣mn−B.val∣,∣mx−B.val∣) max(mnB.val,mxB.val)
并更新答案的最大值。由于 mn ≤ B . val ≤ mx \textit{mn}\le B.\textit{val} \le \textit{mx} mnB.valmx ,上式可化简为 max ⁡ ( B . val − mn , mx − B . val ) \max(B.\textit{val}-\textit{mn},\textit{mx}-B.\textit{val}) max(B.valmn,mxB.val)

class Solution {
    private int ans;

    public int maxAncestorDiff(TreeNode root) {
        dfs(root, root.val, root.val);
        return ans;
    }

    private void dfs(TreeNode node, int mn, int mx) {
        if (node == null) return;
        // 虽然题目要求「不同节点」,但相同节点的差值为 0,不会影响最大差值
        // 所以先更新 mn 和 mx,再计算差值也可以
        // 在这种情况下,一定满足 mn <= node.val <= mx
        mn = Math.min(mn, node.val);
        mx = Math.max(mx, node.val);
        ans = Math.max(ans, Math.max(node.val - mn, mx - node.val));
        dfs(node.left, mn, mx);
        dfs(node.right, mn, mx);
    }
}

换个角度看问题:对于一条从根出发向下的路径,我们要计算的实际上是这条路径上任意两点的最大差值。递归到叶子时, mx \textit{mx} mx 是从根到叶子的路径上的最大值, mn \textit{mn} mn 是从根到叶子的路径上的最小值,所以 mx − mn \textit{mx}-\textit{mn} mxmn 就是从根到叶子的路径上任意两点的最大差值。所以无需每个节点都去更新答案,而是在递归到终点时才去更新答案

class Solution {
private:
    int ans = 0;
    void dfs(TreeNode* r, int mx, int mn) {
        if (r == nullptr) {
            ans = max(mx - mn, ans);
            return;
        }
        mx = max(mx, r->val);
        mn = min(mn, r->val); 
        dfs(r->left, mx, mn);
        dfs(r->right, mx, mn);
    }
public:
    int maxAncestorDiff(TreeNode* root) {
        dfs(root, root->val, root->val);
        return ans;
    }
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n) ,其中 n n n 为二叉树的节点个数。
  • 空间复杂度: O ( n ) O(n) O(n) 。最坏情况下,二叉树退化成一条链,递归需要 O ( n ) O(n) O(n) 的栈空间。

解法2 DFS自底向上

法一的思路是维护 B B B 的祖先节点中的最小值和最大值,我们还可以站在 A A A 的视角,维护 A A A 的子孙节点中的最小值 m n mn mn 和最大值 m x mx mx 。换句话说,最小值和最大值不再作为入参,而是作为返回值,意思是以 A A A 为根的子树中的最小值和最大值。

递归到节点 A A A 时,初始化 m n mn mn m x mx mx A . v a l A.val A.val ,然后递归左右子树,拿到左右子树的最小值和最大值,去更新 m n mn mn m x mx mx ,然后计算
max ⁡ ( ∣ mn − A . val ∣ , ∣ mx − A . val ∣ ) \max(|\textit{mn}-A.\textit{val}|,|\textit{mx}-A.\textit{val}|) max(mnA.val,mxA.val)
并更新答案的最大值。由于 mn ≤ A . val ≤ mx \textit{mn}\le A.\textit{val} \le \textit{mx} mnA.valmx ,上式可化简为
max ⁡ ( A . val − mn , mx − A . val ) \max(A.\textit{val}-\textit{mn},\textit{mx}-A.\textit{val}) max(A.valmn,mxA.val)

class Solution {
    int ans = 0; 
    pair<int, int> dfs(TreeNode *node) {
        if (node == nullptr)
            return {INT_MAX, INT_MIN}; // 保证空节点不影响 mn 和 mx
        int mn = node->val, mx = mn;
        auto [l_mn, l_mx] = dfs(node->left);
        auto [r_mn, r_mx] = dfs(node->right);
        mn = min(mn, min(l_mn, r_mn));
        mx = max(mx, max(l_mx, r_mx));
        ans = max(ans, max(node->val - mn, mx - node->val));
        return {mn, mx};
    } 
public:
    int maxAncestorDiff(TreeNode *root) {
        dfs(root);
        return ans;
    }
};

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n) ,其中 n n n 为二叉树的节点个数。
  • 空间复杂度: O ( n ) O(n) O(n) 。最坏情况下,二叉树退化成一条链,递归需要 O ( n ) O(n) O(n) 的栈空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Direct3D 12——模板——平面镜效果

1.将实物照常渲染到后台缓冲区内&#xff08;不包括镜子&#xff09;。注意&#xff0c;此步骤不修改模 板缓冲区。 2.清理模板缓冲区&#xff0c;将其整体置零。 将实物都绘制到后台缓冲区中&#xff0c;并将模板缓冲区清理为0 &#xff08;用浅灰色来表示&#xff09;。 绘…

socked编程

socket是什么&#xff1f;套接字是什么&#xff1f; 什么是 socket&#xff1f; socket 的原意是“插座”&#xff0c;在计算机通信领域&#xff0c;socket 被翻译为“套接字”&#xff0c;它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定&#xff0c;一台…

Motion Planning学习笔记一:配置空间、图、图搜索、图遍历

学习高飞博士的路径规划课程所总结的学习笔记。 目录 1、配置空间&#xff08;Configuration Space, C-space&#xff09; 2、图&#xff08;Graphs&#xff09; 3、图搜索&#xff08;Graph Search Basis&#xff09; 3.1、总体框架 3.2、两种基本的图遍历算法 3.3、启…

漫谈大数据 - HiveSQL总结(二)查询操作

导语&#xff1a;HiveSQL各关键字详解&#xff0c;hive函数大全&#xff0c;类似于个人记录工具书&#xff0c;后续遇到其他的也会继续加进来。 有关hive库表操作请见上篇&#xff1a;漫谈大数据 - HiveSQL总结&#xff08;一&#xff09;库表操作_昊昊该干饭了的博客-CSDN博客…

一条SQL如何被MySQL架构中的各个组件操作执行的?

文章目录 1. 单表查询SQL在MySQL架构中的各个组件的执行过程2. SELECT的各个关键字在哪里执行&#xff1f;3. 表关联查询SQL在MySQL架构中的各个组件的执行过程4. LEFT JOIN将过滤条件放在子查询中再关联和放在WHERE子句上有什么区别&#xff1f;5. 聚集索引和全表扫描有什么区…

推动开发者平台本土化,高通加速中国XR内容生态发展

随着VR和AR技术快速发展&#xff0c;产品不断成熟&#xff0c;体验也变得越来越优秀。据悉&#xff0c;Meta Quest系列VR头显出货量超2000万台&#xff0c;基本证明了VR开始在消费类电子产品中占据一席之地。与此同时&#xff0c;近两年AR眼镜也在逐渐升温&#xff0c;成为了创…

day17_异常

今日内容 零、 复习昨日 一、作业 二、异常 三、自定义异常 零、 复习昨日 见晨考,重点是String类的方法 StringBuffer和StringBuiler面试问 日期解析和格式化 int i Integer.parseInt(“111”); 一、作业 略,见答案二、异常 2.1 介绍 异常,就是程序出现的不正常的情况. 2.2…

RPA流程自动化技术在金融机构的落地方案详解

金融机构在面向数字化运营的转型过程中&#xff0c;需将智能流程自动化技术整合到数字化转型战略中&#xff0c;规划建设统一的企业流程自动化处理平台&#xff0c;作为数字化运营的辅助支撑类系统&#xff0c;明确流程治理方法和运营模式&#xff0c;确保足够的规模弹性&#…

【深度学习】Softmax回归及前馈神经网络

1 实验内容简介 1.1 实验目的 &#xff08;1&#xff09;熟练掌握tensor相关各种操作&#xff1b; &#xff08;2&#xff09;掌握广义线性回归模型&#xff08;logistic模型、sofmax模型&#xff09;、前馈神经网络模型的原理&#xff1b; &#xff08;3&#xff09;熟练掌…

第一章: uniapp引入axios异步框架

第一章&#xff1a; uniapp引入axios异步框架 在学习uniapp的过程中&#xff0c;发现uniapp框架默认集成request请求框架存在问题&#xff0c;发送请求时在header中塞入token值&#xff0c;而后台接收不到&#xff0c;也就是说uniapp默认的request请求框架&#xff0c;不支持在…

巨烽数字化采购项目启动,甄云助力医疗影像显示领军企业数智化升级

近日&#xff0c;医疗影像显示行业的领军者深圳市巨烽显示科技有限公司&#xff08;以下简称“巨烽”&#xff09;联合甄云科技举办数字化采购管理项目启动会&#xff0c;双方相关部门负责人及项目组成员参加了此次会议。 会上&#xff0c;就巨烽的数字化采购管理系统建设升级…

AI写作机器人-ai文章生成器在线

使用AI续写生成器&#xff0c;让内容创作事半功倍&#xff01; 随着人工智能技术的不断进步和应用&#xff0c;AI续写生成器的出现为内容创作带来了全新的革命。这种技术可以让你的写作事半功倍&#xff0c;让你轻松生成高质量的文章和内容。在这篇文章中&#xff0c;我们将介绍…

如何伪原创-自媒体伪原创软件

批量文字伪原创的作用 批量文字伪原创是指通过对原文进行修改、改写、调整等方式&#xff0c;生成大量新的类似原文的文本。其作用主要包括以下几个方面&#xff1a; 提高文本的独创性&#xff1a;批量伪原创可以有效地避免大量相似内容的出现&#xff0c;从而提高文本的独创性…

我如何学习使用 Jetpack Compose 开发 Android 应用程序

我如何学习使用 Jetpack Compose 开发 Android 应用程序 Jetpack Compose 和 Android 开发简介 2021 年 7 月&#xff0c;Google 发布了用于为 Android 应用构建原生 UI 的全新工具包 1.0 版。Jetpack Compose 是 Android 开发人员的游戏规则改变者&#xff0c;因为它从通过 X…

C#如何解决项目打开问题 error : 找不到指定的 SDK“Microsoft.NET.Sdk.WindowsDesktop”

错误提示&#xff0c;问题描述 后来发现&#xff0c;直接安装rider还是不能解决解决&#xff08;会自动配置关联&#xff08;path等&#xff09;&#xff0c;甚至自动下载的&#xff0c;官方的visual studio反而不会&#xff0c;之后再详细看怎么弄了&#xff09; VS2022项目…

IDEA 用上这款免费 GPT4 插件,生产力爆表了

大家好&#xff0c;我是一航&#xff01; 早前给大家分享过GPT的一些玩法&#xff0c;但是依旧有很多铁子没有掌握魔法的奥秘&#xff0c;始终没有用上&#xff1b;前两天&#xff0c;一兄台分享给我一款 IDE 插件&#xff1a;Bito-ChatGPT &#xff0c;安装就能直接在IDE中使…

如何选择合适的网络自动化工具

通过网络自动化工具实现网络自动化是所有网络组织的关键。如果没有合适的网络自动化工具&#xff0c;拥有由许多设备组成的大型网络环境的组织将无法执行重要操作&#xff0c;例如按时备份配置、实时跟踪不需要的更改以及遵守行业法规。当组织未能使用正确的网络自动化工具来执…

yolov8训练自己的数据集遇到的问题

训练分类模型 1.如何更改模型的类别数nc 根据本地模型配置文件.yaml可以设置nc 但是&#xff0c;这里无法用到预训练模型.pt模型文件&#xff0c;预训练模型的权重参数是在大数据集上训练得到的&#xff0c;泛化性能可能比较好&#xff0c;所以&#xff0c;下载了官方的分类…

Flink+Kafka、Pulsar实现端到端的exactly-once语义

End-to-End Exactly-Once Processing in Apache Flink with Apache Kafka 2017年12月Apache Flink社区发布了1.4版本。该版本正式引入了一个里程碑式的功能&#xff1a;两阶段提交Sink&#xff0c;即TwoPhaseCommitSinkFunction。该SinkFunction提取并封装了两阶段提交协议中的…

【离散数学】测试五 图论

1. n层正则m叉树一共有()片树叶。 A. nm B. mn C. mn 正确答案: B 2. 下图是一棵最优二叉树 A. 对 B. 错 正确答案: B 3. 要构造权为1,4,9,16,25,36,49,64,81,100一棵最优二叉树,则必须先构造权为5,9,16,25,36,49,64,81,100一棵最优二叉树. A. 对 B. 错 …