赞
踩
有一个有 n
个节点的有向图,节点按 0
到 n - 1
编号。图由一个 索引从 0 开始 的 2D 整数数组 graph
表示, graph[i]
是与节点 i
相邻的节点的整数数组,这意味着从节点 i
到 graph[i]
中的每个节点都有一条边。
如果一个节点没有连出的有向边,则该节点是 终端节点 。如果从该节点开始的所有可能路径都通向 终端节点 ,则该节点为 安全节点 。
返回一个由图中所有 安全节点 组成的数组作为答案。答案数组中的元素应当按 升序 排列。
示例1:
输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]] 输出:[2,4,5,6] 解释:示意图如上。 节点 5 和节点 6 是终端节点,因为它们都没有出边。 从节点 2、4、5 和 6 开始的所有路径都指向节点 5 或 6 。
示例 2:
输入:graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]] 输出:[4] 解释: 只有节点 4 是终端节点,从节点 4 开始的所有路径都通向节点 4 。
提示:
n == graph.length
1 <= n <= 10^4
0 <= graph[i].length <= n
0 <= graph[i][j] <= n - 1
graph[i]
按严格递增顺序排列。[1, 4 * 10^4]
内。思路:拓扑排序的变形,从后往前找。
1、采用邻接表来表示有向图,抽象成:
(1)一个二维数组,里面每一个一维数组存以该索引为顶点的前趋顶点,题目中给的graph给的是后继节点,要初始化转化一下。
(2)一个一维数组 out, 来表示每个顶点的出度。
2、我们开始先根据输入来建立这个有向图,并将出度数组也初始化好。
3、设置一个stack:
(1)将所有出度为0的点压栈。
(2)从栈中退出栈顶元素输出,并把该顶点引入的所有有向边删去,也就是把它的各个前趋顶点的出度数-1。
(3)将新的出度数为零的顶点再入堆栈。
(4)重复过程(2)-(3),直到栈为空。最后,所有出度为零的顶点,是安全节点。
- class Solution {
- public:
- vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
- //建立一个二维数组,里面每一个一维数组存以该索引为顶点的前趋顶点
- vector<vector<int> > g(graph.size());
- for(int i=0; i<graph.size(); ++i){
- for(int j=0; j<graph[i].size(); ++j){
- //i的后继节点是graph[i][j]
- g[graph[i][j]].push_back(i);
- }
- }
- vector<int>out(graph.size());//存出度数
- //计算每一个顶点的出度数
- for(int i=0; i<graph.size(); ++i){
- out[i]=graph[i].size();
- }
- stack<int>s;
- for(int i=0; i<out.size(); ++i){
- if(out[i]==0) s.push(i);
- }
- vector<int>re;//存结果
- while(!s.empty()){
- int n=s.top();
- s.pop();
- re.push_back(n);
- //把该顶点的各个前趋顶点的出度数-1
- for(auto x:g[n]){
- if(--out[x]==0){
- s.push(x);
- }
- }
- }
- sort(re.begin(), re.end());//题目要求结果返回一个有序的数组。
- return re;
- }
- };

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。