From 3c9810e7de48bd6818bdbc3e357fc66d3a4edf83 Mon Sep 17 00:00:00 2001
From: Matej Focko <me@mfocko.xyz>
Date: Fri, 24 Jan 2025 17:45:57 +0100
Subject: [PATCH] =?UTF-8?q?java:=20add=20=C2=AB802.=20Find=20Eventual=20Sa?=
 =?UTF-8?q?fe=20States=C2=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

URL:	https://leetcode.com/problems/find-eventual-safe-states/
Signed-off-by: Matej Focko <me@mfocko.xyz>
---
 java/find-eventual-safe-states.java | 60 +++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 java/find-eventual-safe-states.java

diff --git a/java/find-eventual-safe-states.java b/java/find-eventual-safe-states.java
new file mode 100644
index 0000000..a611d62
--- /dev/null
+++ b/java/find-eventual-safe-states.java
@@ -0,0 +1,60 @@
+class Solution {
+  private static class DFS {
+    private int[][] graph;
+    private boolean[] visited;
+    private boolean[] open;
+
+    public DFS(int[][] graph) {
+      this.graph = graph;
+      visited = new boolean[graph.length];
+      open = new boolean[graph.length];
+    }
+
+    public boolean hasInCycle(int u) {
+      return open[u];
+    }
+
+    public boolean run(int u) {
+      if (open[u]) {
+        // found loop
+        return true;
+      }
+
+      if (visited[u]) {
+        // searched vertex
+        return false;
+      }
+
+      visited[u] = true;
+
+      open[u] = true;
+      for (var v : graph[u]) {
+        if (run(v)) {
+          // loops stay open
+          return true;
+        }
+      }
+      open[u] = false;
+
+      return false;
+    }
+  }
+
+  public List<Integer> eventualSafeNodes(int[][] graph) {
+    int n = graph.length;
+
+    var runner = new DFS(graph);
+    for (var i = 0; i < n; ++i) {
+      runner.run(i);
+    }
+
+    var safe = new ArrayList<Integer>();
+    for (var i = 0; i < n; ++i) {
+      if (!runner.hasInCycle(i)) {
+        safe.add(i);
+      }
+    }
+
+    return safe;
+  }
+}