2024.4.24力扣每日一题——感染二叉树需要的总时间

news/2024/10/21 13:36:51/

2024.4.24

      • 题目来源
      • 我的题解
        • 方法一 转化为图+广度优先搜索
        • 方法二 记录父节点+DFS
        • 方法三 一次遍历+树的直径

题目来源

力扣每日一题;题序:2385

我的题解

方法一 转化为图+广度优先搜索

先将树转换为图,然后进行广度优先搜索进行感染模拟

时间复杂度:O(n)
空间复杂度:O(n)

java">class Solution {int size=0;public int amountOfTime(TreeNode root, int start) {// List<Integer>[] g=createGraph(root);Map<Integer,List<Integer>> map=createMap(root);// System.out.println(map);Set<Integer> set=new HashSet<>();set.add(start);Queue<Integer> queue=new LinkedList<>();queue.offer(start);int res=0;while(!queue.isEmpty()){int sz=queue.size();for(int i=0;i<sz;i++){List<Integer> t=map.get(queue.poll());if(t==null)continue;for(Integer e:t){if(set.add(e))queue.offer(e);}}res++;}//最后一层会多计算一次return res-1;}public Map<Integer,List<Integer>> createMap(TreeNode root){Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);Map<Integer,List<Integer>> map=new HashMap<>();while(!queue.isEmpty()){int sz=queue.size();for(int i=0;i<sz;i++){TreeNode tree=queue.poll();int t=tree.val;if(tree.left!=null){addEdge(t,tree.left.val,map);queue.offer(tree.left);}if(tree.right!=null){addEdge(t,tree.right.val,map);queue.offer(tree.right);}}size+=sz;}return map;}public void addEdge(int from,int to ,Map<Integer,List<Integer>> map){List<Integer> l1=map.getOrDefault(from,new ArrayList<>());List<Integer> l2=map.getOrDefault(to,new ArrayList<>());l1.add(to);l2.add(from);map.put(from,l1);map.put(to,l2);}
}
方法二 记录父节点+DFS

参考灵神的代码
首先从 root出发 DFS 这棵树,找到节点值为 start 的节点 startNode。DFS 的同时,用一个哈希表(或者数组)记录每个节点的父节点。
然后从 startNode出发 DFS 这棵树,求出二叉树的最大深度,即为答案(把 startNode 的深度当作 0)。注意除了递归左右儿子以外,还需要递归父节点。为避免重复访问节点,可以添加一个递归参数 from,表示当前节点是从节点 from 过来的,不去重复访问节点 from。

时间复杂度:O(n)
空间复杂度:O(n)

java">class Solution {private TreeNode startNode;private final Map<TreeNode, TreeNode> fa = new HashMap<>();public int amountOfTime(TreeNode root, int start) {dfs(root, null, start);return maxDepth(startNode, startNode);}private void dfs(TreeNode node, TreeNode from, int start) {if (node == null) {return;}fa.put(node, from); // 记录每个节点的父节点if (node.val == start) {startNode = node; // 找到 start}dfs(node.left, node, start);dfs(node.right, node, start);}private int maxDepth(TreeNode node, TreeNode from) {if (node == null) {return -1; // 注意这里是 -1,因为 start 的深度为 0}int res = -1;if (node.left != from) {res = Math.max(res, maxDepth(node.left, node));}if (node.right != from) {res = Math.max(res, maxDepth(node.right, node));}if (fa.get(node) != from) {res = Math.max(res, maxDepth(fa.get(node), node));}return res + 1;}
}
方法三 一次遍历+树的直径

参考灵神的代码
实质就是求 以start为直径端点的树的直径

时间复杂度:O(n)
空间复杂度:O(n)

java">class Solution {private int ans;public int amountOfTime(TreeNode root, int start) {dfs(root, start);return ans;}private int[] dfs(TreeNode node, int start) {if (node == null) {return new int[]{0, 0};}int[] leftRes = dfs(node.left, start);int[] rightRes = dfs(node.right, start);int lLen = leftRes[0], lFound = leftRes[1];int rLen = rightRes[0], rFound = rightRes[1];if (node.val == start) {// 计算子树 start 的最大深度// 注意这里和方法一的区别,max 后面没有 +1,所以算出的也是最大深度ans = Math.max(lLen, rLen);return new int[]{1, 1}; // 找到了 start}if (lFound == 1 || rFound == 1) {// 只有在左子树或右子树包含 start 时,才能更新答案ans = Math.max(ans, lLen + rLen); // 两条链拼成直径// 保证 start 是直径端点return new int[]{(lFound == 1 ? lLen : rLen) + 1, 1};}return new int[]{Math.max(lLen, rLen) + 1, 0};}
}

灵神是真的强!!!!!!!!!!

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~


http://www.ppmy.cn/news/1442613.html

相关文章

OSD图像技术

OSD&#xff08;On-Screen Display&#xff09;图像技术&#xff0c;是指在显示设备上叠加显示文字、图形或图像的功能。这项技术广泛应用于电视、电脑显示器、安防监控系统中的摄像头、以及其他各类显示界面中。 OSD允许用户在不干扰主画面内容的情况下&#xff0c;查看或调整…

使用FunASR处理语音识别

FunASR是阿里的一个语音识别工具&#xff0c;比SpeechRecognition功能多安装也很简单&#xff1b; 官方介绍&#xff1a;FunASR是一个基础语音识别工具包&#xff0c;提供多种功能&#xff0c;包括语音识别&#xff08;ASR&#xff09;、语音端点检测&#xff08;VAD&#xff…

【win10移动热点,提示正在获取ip地址...】

检查 Wired AutoConfig/ WLAN AutoConfig 服务运行 电脑→管理→服务和应用程序→服务&#xff1a;AutoConfig 有线网络无线网卡 1.开启wifi热点&#xff0c;自动生成“本地连接*10”&#xff1b; 2.配置Wired LAN网络共享 仅无线网卡 1. 开启wifi热点&#xff0c;自动生…

win安装vue并运行 vue-admin-template

1. Node Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;用于构建高性能、可扩展的网络应用程序。它使得开发者能够在服务器端使用JavaScript编程&#xff0c;同时支持事件驱动、非阻塞I/O模型&#xff0c;适用于构建实时应用和高吞吐量的网络服务。 1.1 …

洛谷 P3810 【模板】三维偏序(陌上花开)

【模板】三维偏序&#xff08;陌上花开&#xff09; 题目描述 有 n n n 个元素&#xff0c;第 i i i 个元素有 a i , b i , c i a_i,b_i,c_i ai​,bi​,ci​ 三个属性&#xff0c;设 f ( i ) f(i) f(i) 表示满足 a j ≤ a i a_j \leq a_i aj​≤ai​ 且 b j ≤ b i b_j…

shell 实现对Hive表字段脱敏写入新表

数据安全管理&#xff0c;本shell 实现对hive源表敏感字段进行md5加密&#xff0c;然后写入新表&#xff1b; read -p 交互输入&#xff1a;要脱敏的hive表、分区,示例: test_db.table_name 20240331 生成更新hive分区表的hql: insert overwrite table xxx 备注&#xff1a;仅供…

05_c/c++开源库 spdlog日志库

1.简介与安装 spdlog 是一个用于 C 的高性能、易用的日志库。它提供了丰富的日志功能&#xff0c;包括多种日志级别、格式化输出、异步日志、自定义日志接收器等。spdlog 是一个轻量级的库&#xff0c;性能优越&#xff0c;非常适合用于需要高性能日志记录的场景。 特点 高性…

【FPGA】优化设计指南(一):设计原则

目录 避免采用不可综合的语句设计时采用同步的时钟组合逻辑与毛刺异步复位与同步复位动态分析与静态分析功能流水线时序违例乒乓操作面积和速度的平衡避免采用不可综合的语句 1.#1000延时语句 2.除法运算/,除非除数为2的整次幂 3.实数类型不可综合(real) 4.综上,使用可综合…