稀碎从零算法笔记Day59-LeetCode: 感染二叉树需要的总时间

题型:树、图、BFS、DFS

链接:2385. 感染二叉树需要的总时间 - 力扣(LeetCode)

来源:LeetCode

题目描述

给你一棵二叉树的根节点 root ,二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟,感染 将会从值为 start 的节点开始爆发。

每分钟,如果节点满足以下全部条件,就会被感染:

  • 节点此前还没有感染。
  • 节点与一个已感染节点相邻。

返回感染整棵树需要的分钟数*。*

题目样例

示例 1:

复制代码
输入:root = [1,5,3,null,4,10,6,9,2], start = 3
输出:4
解释:节点按以下过程被感染:
- 第 0 分钟:节点 3
- 第 1 分钟:节点 1、10、6
- 第 2 分钟:节点5
- 第 3 分钟:节点 4
- 第 4 分钟:节点 9 和 2
感染整棵树需要 4 分钟,所以返回 4 。

示例 2:

复制代码
输入:root = [1], start = 1
输出:0
解释:第 0 分钟,树中唯一一个节点处于感染状态,返回 0 。

提示:

  • 树中节点的数目在范围 [1, 105] 内
  • 1 <= Node.val <= 105
  • 每个节点的值 互不相同
  • 树中必定存在值为 start 的节点

题目思路

乍一看能感觉出来是层序遍历(广度优先遍历),或者说求树的最大深度?

但是他不是树的遍历方式------因为start不一定是root结点

如果是一个图进行,那问题也会简单许多------直接BFS拓扑排序就行,但这是个树,所以可以考虑先把 树转化为图 然后进行BFS

那问题就可以转化为 ①将树转化为图 ② BFS遍历图

将树转化为图可以DFS遍历一次:图的数据结构可以用 vector<int> 来存相连的点的val

转化为图后可以进行从 start 开始的 BFS ---- 用queue来存拓扑排序的点的 【相连的点】 。遍历完一次后就可以将【相连的点】添加到 queue 中。

考虑到一个点可能被多个点相连进而可能被访问多次,可以用 visit 数组来存一下是否被访问过

C++代码

cpp 复制代码
class Solution {
public:
    int amountOfTime(TreeNode* root, int start) {
        // int存time vector<int> 存孩子/父节点
        unordered_map<int,vector<int>>graph;
        // lambda定义dfs
        function<void(TreeNode *)>dfs = [&](TreeNode * node){
            //将左右孩子整合为child
            for(TreeNode *child : vector<TreeNode *> {node ->left,node -> right}){
                if(child != nullptr){
                    // 将孩子结点添加到数组中 ------ 数组存相连的点
                    graph[node -> val].push_back(child -> val);
                    // 将父亲结点添加到数组中 ------ 数组存与这个点连接的结点
                    graph[child -> val].push_back(node -> val);
                    dfs(child);
                }
            }
        };
        // 相当于二维矩阵 来将一个树转化为图
        dfs(root);
        // 队列存拓扑排序的顺序  但还存遍历的次数
        queue<vector<int>> Q;
        Q.push({start,0});
        //相当于在有图的情况下 进行BFS
        // 存储遍历过的点
        unordered_set<int> visited;
        visited.insert(start);
        int time = 0;
        while(!Q.empty()){
            auto temp =Q.front() ;
            Q.pop();
            int nodeVal = temp[0];
            time = temp[1];
            // 遍历点对应的相连的结点
            for(int Val : graph[nodeVal]){
                if(!visited.count(Val)){
                    Q.push({Val,time+1});
                    visited.insert(Val);
                }
            }


        }
        return time;
    }
};

结算页面

相关推荐
一隅论数智3 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
深圳老胡3 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
彧azz4 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试