🧠
DFS with Early Exit and Visited Array
💡 This approach uses DFS with a boolean visited array for O(1) checks and stops early if all rooms are visited, improving efficiency.
Intuition
Use DFS to explore rooms, mark visited using an array for faster access, and stop recursion once all rooms are visited.
Algorithm
- Initialize a boolean visited array and a counter for visited rooms.
- Start DFS from room 0, mark visited and increment counter.
- For each key, if not visited, recursively DFS.
- If counter equals total rooms, stop recursion early.
- Return true if all rooms visited, else false.
💡 Early stopping avoids exploring unnecessary paths once the goal is met, improving runtime.
def canVisitAllRooms(rooms):
n = len(rooms)
visited = [False] * n
count = 0
def dfs(room):
nonlocal count
if visited[room]:
return
visited[room] = True
count += 1
if count == n:
return
for key in rooms[room]:
dfs(key)
dfs(0)
return count == n
# Driver code
if __name__ == '__main__':
rooms = [[1],[2],[3],[]]
print(canVisitAllRooms(rooms)) # True
Line Notes
visited = [False] * nBoolean array for O(1) visited checks
count = 0Count how many rooms have been visited
if visited[room]: returnSkip already visited rooms to avoid cycles
if count == n: returnEarly exit when all rooms visited
import java.util.*;
public class KeysAndRooms {
private static int count = 0;
public static boolean canVisitAllRooms(List<List<Integer>> rooms) {
int n = rooms.size();
boolean[] visited = new boolean[n];
count = 0;
dfs(0, rooms, visited, n);
return count == n;
}
private static void dfs(int room, List<List<Integer>> rooms, boolean[] visited, int n) {
if (visited[room]) return;
visited[room] = true;
count++;
if (count == n) return;
for (int key : rooms.get(room)) {
dfs(key, rooms, visited, n);
}
}
public static void main(String[] args) {
List<List<Integer>> rooms = new ArrayList<>();
rooms.add(Arrays.asList(1));
rooms.add(Arrays.asList(2));
rooms.add(Arrays.asList(3));
rooms.add(Collections.emptyList());
System.out.println(canVisitAllRooms(rooms)); // true
}
}
Line Notes
boolean[] visited = new boolean[n];Use boolean array for fast visited checks
if (visited[room]) return;Avoid revisiting rooms
count++;Increment count when visiting a new room
if (count == n) return;Stop recursion early if all rooms visited
#include <iostream>
#include <vector>
using namespace std;
int count = 0;
void dfs(int room, const vector<vector<int>>& rooms, vector<bool>& visited, int n) {
if (visited[room]) return;
visited[room] = true;
count++;
if (count == n) return;
for (int key : rooms[room]) {
dfs(key, rooms, visited, n);
}
}
bool canVisitAllRooms(const vector<vector<int>>& rooms) {
int n = rooms.size();
vector<bool> visited(n, false);
count = 0;
dfs(0, rooms, visited, n);
return count == n;
}
int main() {
vector<vector<int>> rooms = {{1}, {2}, {3}, {}};
cout << (canVisitAllRooms(rooms) ? "true" : "false") << endl;
return 0;
}
Line Notes
vector<bool> visited(n, false);Boolean vector for visited rooms
if (visited[room]) return;Skip rooms already visited
count++;Track number of visited rooms
if (count == n) return;Early exit to save time
let count = 0;
function canVisitAllRooms(rooms) {
const n = rooms.length;
const visited = new Array(n).fill(false);
function dfs(room) {
if (visited[room]) return;
visited[room] = true;
count++;
if (count === n) return;
for (const key of rooms[room]) {
dfs(key);
}
}
dfs(0);
return count === n;
}
// Test
console.log(canVisitAllRooms([[1],[2],[3],[]])); // true
Line Notes
const visited = new Array(n).fill(false);Boolean array for visited rooms
if (visited[room]) return;Avoid revisiting rooms
count++;Count visited rooms
if (count === n) return;Stop recursion early if all rooms visited
Each room and key is visited once, early exit can improve average runtime.
💡 For large inputs, early stopping can save significant time by avoiding unnecessary exploration.
Interview Verdict: Accepted
This is the most optimized DFS approach, combining speed and safety against stack overflow.