稀碎从零算法笔记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;
    }
};

结算页面

相关推荐
黄俊懿2 分钟前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
新缸中之脑2 分钟前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
夜雨翦春韭22 分钟前
【代码随想录Day29】贪心算法Part03
java·数据结构·算法·leetcode·贪心算法
笑鸿的学习笔记24 分钟前
工具笔记之生成图表和可视化的标记语言Mermaid
笔记
Curry_Math39 分钟前
Acwing 区间DP & 计数类DP
算法
Tisfy1 小时前
LeetCode 1928.规定时间内到达终点的最小花费:动态规划
算法·leetcode·动态规划·
kissSimple1 小时前
UE行为树编辑器图文笔记
笔记·ue5·编辑器·unreal engine·unreal engine 5
ん贤1 小时前
贪心算法.
算法·贪心算法
cndes1 小时前
大数据算法的思维
大数据·算法·支持向量机
l1x1n01 小时前
DOS 命令学习笔记
笔记·学习·web安全