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

结算页面

相关推荐
ling___xi4 小时前
《计算机网络》计网3小时期末速成课各版本教程都可用谢稀仁湖科大版都可用_哔哩哔哩_bilibili(笔记)
网络·笔记·计算机网络
yyy(十一月限定版)4 小时前
寒假集训4——二分排序
算法
星火开发设计4 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
醉颜凉4 小时前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐4 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗4 小时前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子4 小时前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
培风图南以星河揽胜4 小时前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
算法_小学生4 小时前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2594 小时前
力扣hot100 - 234、回文链表
算法·leetcode·链表