力扣—802找到最终的安全状态

题目描述

在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走。 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止。

现在, 如果我们最后能走到终点,那么我们的起始节点是最终安全的。 更具体地说, 存在一个自然数 K,  无论选择从哪里开始行走, 我们走了不到 K 步后必能停止在一个终点。

哪些节点最终是安全的? 结果返回一个有序的数组。

该有向图有 N 个节点,标签为 0, 1, ..., N-1, 其中 N 是 graph 的节点数.  图以以下的形式给出: graph[i] 是节点 j 的一个列表,满足 (i, j) 是图的一条有向边。

示例:
输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]]
输出:[2,4,5,6]
这里是上图的示意图。

Illustration of graph

解题思路

图拓扑排序

如果一个节点没有出度,那么这个节点自然就是安全节点,并且如果有其他节点链接到这个没有出度的节点,那么删除这个边后,若那个节点没有出度了,那么那个节点也是安全的。

这个题需要找出的节点是没有出度的节点(以及把这些节点去掉之后没有出度的节点),这样可以看出其实就是一个拓扑排序的过程。
知道是拓扑排序就很好理解了。只需要一个逆邻接表再维护一个出度表就行了。出度为0就出名该节点是最终的节点了,这就是寻找的安全节点,再根据逆邻接表找出哪些节点连接找这个节点,将这个节点的出度减一。如果又有节点的出度是0则说明该节点也是安全节点。

class Solution(object):
    def eventualSafeNodes(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: List[int]
        """
        n = len(graph)
        visit = [False] * n
        out_degree = [0] * n
        reversed_table = [[] for _ in range(n)]
        for i in range(n):
            out_degree[i] = len(graph[i])
            for item in graph[i]:
                reversed_table[item].append(i)
        queue = []
        result = []
        for i in range(n):
            if out_degree[i] == 0:
                queue.append(i)
        while queue:
            cur = queue.pop(0)
            visit[cur] = 1
            for num in reversed_table[cur]:
                out_degree[num] -= 1
                if out_degree[num] == 0:
                    queue.append(num)
        for i in range(n):
            if visit[i] == 1:
                result.append(i)
        return result

S = Solution()
print(S.eventualSafeNodes([[1,2],[2,3],[5],[0],[5],[],[]]))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值