leetcode-802:找到最终的安全状态

简介: leetcode-802:找到最终的安全状态

题目

题目链接

在有向图中,以某个节点为起始节点,从该点出发,每一步沿着图中的一条有向边行走。如果到达的节点是终点(即它没有连出的有向边),则停止。

对于一个起始节点,如果从该节点出发,无论每一步选择沿哪条有向边行走,最后必然在有限步内到达终点,则将该起始节点称作是 安全 的。

返回一个由图中所有安全的起始节点组成的数组作为答案。答案数组中的元素应当按 升序 排列。

该有向图有 n 个节点,按 0 到 n - 1 编号,其中 n 是 graph 的节点数。图以下述形式给出:graph[i] 是编号 j 节点的一个列表,满足 (i, j) 是图的一条有向边。

示例 1:

输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]]
输出:[2,4,5,6]
解释:示意图如上。

示例 2:

输入:graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
输出:[4]

解题

方法一:拓扑排序

参考链接

若一个节点的出边相连的点都是安全的,则该点也是安全的,在反向图中,inDeg就是记录出边数量,每次从安全点遍历到该点,都会使得inDeg-1,当inDeg==0,代表每个节点出边相连的点都是安全的。

graph[x].size()是正向图的出度,也就是反向图的入度

class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        int n=graph.size();
        //获得反向图和每个顶点的入度
        vector<vector<int>> rg(n);//reversed graph
        vector<int> inDeg(n);
        for(int x=0;x<n;x++){
            for(int y:graph[x]){
                rg[y].push_back(x);
            }
            inDeg[x]=graph[x].size();//反向图的入度是正向图的出度
        }
        //初始化(将 入度为0的顶点,加入队列)
        queue<int> q;
        for(int i=0;i<n;i++){
            if(inDeg[i]==0) q.push(i);
        }
        //将入度为0的顶点的相邻边删去,相邻顶点入度-1,如果入度为0,加入到队列中
        while(!q.empty()){
            int y=q.front();
            q.pop();
            for(int x:rg[y]){
                if(--inDeg[x]==0){
                    q.push(x);
                }
            }
        }
        //入度为0的顶点 即为安全点 
        vector<int> res;
        for(int i=0;i<n;i++){
            if(inDeg[i]==0) res.push_back(i);
        }
        return res;
    }
};

方法二:深度优先搜索 + 三色标记法

解答

由于color[x]=1后面遍历每个出边,如果出边对应顶点都是安全点,那么color[x]=2,如果不安全则为color[x]=1

因此当再次遍历到的时候,访问过的话color[x]>0。出边的顶点是不安全的,那么该顶点一定是不安全的,出边的顶点是安全的,那么该顶点是安全的。

写法一

由于用到多次传参,比如graph和color,可以使用function包装lambda表达式,减少代码量

class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>> &graph) {
        int n = graph.size();
        vector<int> color(n);
        function<bool(int)> safe = [&](int x) {
            if (color[x] > 0) {
                return color[x] == 2;//如果该顶点是安全点,就返回true
            }
            color[x] = 1;
            for (int y : graph[x]) {//任意的出边都要是安全点才行,否则该顶点就不是安全顶点
                if (!safe(y)) {
                    return false;
                }
            }
            color[x] = 2;//任意出边都是安全点,因此该顶点是安全点
            return true;
        };
        vector<int> ans;
        for (int i = 0; i < n; ++i) {
            if (safe(i)) {
                ans.push_back(i);
            }
        }
        return ans;
    }
};

补充

lambda表达式相关链接

function在这当作lambda表达式的装饰器,统一成function类型,方便管理和使用,function 中bool为返回值,int为形参

写法二

class Solution {
public:
    bool safe(int x,vector<vector<int>>& graph,vector<int>& color){
        if(color[x]>0){
            return color[x]==2;
        }
        color[x]=1;
        for(int y:graph[x]){
            if(!safe(y,graph,color)) return false;
        }
        color[x]=2;
        return true;
    }
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        int n=graph.size();
        vector<int> color(n);
        vector<int> res;
        for(int i=0;i<n;i++){
            if(safe(i,graph,color)) res.push_back(i);
        }
        return res;
    }
};


相关文章
|
3月前
leetcode-2115:从给定原材料中找到所有可以做出的菜
leetcode-2115:从给定原材料中找到所有可以做出的菜
23 0
|
4月前
|
自然语言处理 网络协议 应用服务中间件
记录一次问题的解决过程
记录一次问题的解决过程
利用map和cod文件定位崩溃位置的例子和习题
利用map和cod文件定位崩溃位置的例子和习题
|
8月前
|
算法 安全 机器人
算法提高:计算几何基础 | 判断包含关系
计算几何是计算机科学的一个重要分支,主要研究几何形体的数学描述和计算机描述,在现代工程和数学领域,以及计算机辅助设计、地理信息系统、图形学、机器人技术、超大规模集成电路设计和统计等诸多领域都有重要的用途。在 ACM 竞赛中,出题相对独立,曾出现过与图论、动态规划相结合的题,大多数计算几何问题用程序实现都比较复杂。常用算法包括经典的凸包求解、离散化及扫描线算法、旋转卡壳、半平面交等。本文介绍计算几何常用算法——包含关系。
106 0
|
8月前
|
算法 C语言 C++
【模拟】特别数的和、移动距离、连号区间、错误票据思路详解及代码实现
取出最后一位,然后将n除去最后一位,将刚刚取出的进行判定。
46 0
|
11月前
在给定范围的数据中找到含有6的数据个数
在给定范围的数据中找到含有6的数据个数
|
人工智能
LeetCode 1389. 按既定顺序创建目标数组
给你一个字符串 s,它由数字('0' - '9')和 '#' 组成。我们希望按下述规则将 s 映射为一些小写英文字符
62 0
|
存储 算法 Java
算法打卡Day5_lecode_448. 找到所有数组中消失的数字
算法打卡Day5_lecode_448. 找到所有数组中消失的数字
算法打卡Day5_lecode_448. 找到所有数组中消失的数字
找到所有数组中消失的数字(算法题)
找到所有数组中消失的数字(算法题)

热门文章

最新文章