Opening the reading…
Opening the reading…
GRAPHS › DFS AND BFS ON GRAPHS
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →Room 0 is the only place you can enter initially, so every successful visit must begin there. Once you enter a room, each key inside gives you a possible next room. That means a key from room u to room v behaves exactly like a directed graph edge from u to v.
The question is therefore whether every room is reachable from room 0. Start at room 0, follow every key you can obtain, and continue from each newly reached room. A visited array prevents cycles and repeated work: finding a key for a room you already reached cannot unlock anything new.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | O(n + m) | Each reachable room is removed from the stack once, and the keys in that room are scanned once. A key entry is therefore inspected at most once, while the room bookkeeping contributes O(n). |
| Space | O(n) | The visited array uses O(n) space and the stack holds at most n room numbers. The boolean result is not stored as output, and there is no separate output structure; in the worst shape, all rooms can be reachable and occupy the stack or visited array. |
#include <vector>
#include <stack>
using namespace std;
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = static_cast<int>(rooms.size());
vector<bool> visited(n, false);
stack<int> st;
st.push(0);
visited[0] = true;
int seen = 1;
while (!st.empty()) {
int u = st.top();
st.pop();
for (int v : rooms[u]) {
if (v >= 0 && v < n && !visited[v]) {
visited[v] = true;
seen++;
st.push(v);
}
}
}
return seen == n;
}
};The important placement is visited[v] = true before st.push(v). Two different rooms may contain keys to the same destination, and a cycle may lead back to an earlier room. Marking at discovery means the first key claims that room immediately, so later keys cannot add duplicate stack entries.
The seen counter is not required; you could scan visited after the search. It makes the final test direct: every successful discovery increases seen once, so seen == n means every room belongs to the reachable region. The bounds check is defensive because the stated input keeps every key between 0 and n - 1.
#include <vector>
using namespace std;
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = static_cast<int>(rooms.size());
vector<bool> visited(n, false);
int seen = 0;
dfs(0, rooms, visited, seen);
return seen == n;
}
private:
void dfs(int u, const vector<vector<int>>& rooms,
vector<bool>& visited, int& seen) {
visited[u] = true;
seen++;
for (int v : rooms[u]) {
if (!visited[v]) {
dfs(v, rooms, visited, seen);
}
}
}
};This is a different arrangement, not an asymptotic optimisation. The recursive call stack replaces the explicit stack, so both versions use O(n) extra space in the worst case and inspect O(n + m) data. The iterative form gives you explicit control over pending rooms and avoids depending on the runtime call stack when a long chain of rooms is possible.