
방향 그래프에서 어떤 경로로 가든 결국 터미널 노드(나가는 간선 없음)에 도착하는 노드를 오름차순으로 반환한다.
safe하지 않다는 것은 사이클에 빠질 수 있다는 뜻이다.
그래서 DFS로 사이클을 찾으면 되고, 노드 상태를 세 가지로 관리한다.
0 미방문1 방문 중 (현재 DFS 경로 위에 있음) 또는 unsafe로 확정됨2 safe로 확정됨DFS 도중 상태가 1인 노드를 다시 만나면 사이클이다.
function eventualSafeNodes(graph: number[][]): number[] {
const graphLen = graph.length;
const state = Array(graphLen).fill(0);
const isSafe = (n: number) => {
if (state[n] > 0) return state[n] === 2;
state[n] = 1;
for (const neighbor of graph[n]) if (!isSafe(neighbor)) return false;
state[n] = 2;
return true;
};
const safeNodes = [];
for (let i = 0; i < graphLen; i++) if (isSafe(i)) safeNodes.push(i);
return safeNodes;
}
1로 표시하고 이웃을 탐색한다.false를 반환한다. 이때 노드는 1로 남아서 unsafe로 확정된다.2로 바꾼다.0부터 차례로 검사하므로 결과는 따로 정렬하지 않아도 오름차순이다.1 하나가 "방문 중"과 "unsafe 확정"을 함께 표현한다는 점이 포인트다. 방문 중인 노드를 다시 만난 경우와 unsafe 노드를 만난 경우 모두 결과는 false이므로 구분할 필요가 없다.
visited를 쌓기만 하고 빼지 않음 → 두 경로가 한 노드로 합류하는 다이아몬드 모양을 사이클로 오인한다.visited로 탐색 → 결과를 재사용하지 못해 같은 노드를 반복 탐색하고 시간초과가 난다.