## DEV Community is a community of 892,765 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

seanpgallivan

Posted on

# Solution: Keys and Rooms

This is part of a series of Leetcode solution explanations (index). If you liked this solution or found it useful, please like this post and/or upvote my solution post on Leetcode's forums.

#### Description:

(Jump to: Solution Idea || Code: JavaScript | Python | Java | C++)

There are `N` rooms and you start in room `0`. Each room has a distinct number in `0, 1, 2, ..., N-1`, and each room may have some keys to access the next room.

Formally, each room `i` has a list of keys `rooms[i]`, and each key `rooms[i][j]` is an integer in `[0, 1, ..., N-1]` where `N = rooms.length`. A key `rooms[i][j] = v` opens the room with number `v`.

Initially, all the rooms start locked (except for room `0`).

You can walk back and forth between rooms freely.

Return `true` if and only if you can enter every room.

#### Examples:

Example 1:
Input: [[1],[2],[3],[]]
Output: true
Explanation: We start in room 0, and pick up key 1.
We then go to room 1, and pick up key 2.
We then go to room 2, and pick up key 3.
We then go to room 3.
Since we were able to go to every room, we return true.
Example 2:
Input: [[1,3],[3,0,1],[2],[0]]
Output: false
Explanation: We can't enter the room with number 2.

#### Constraints:

• `1 <= rooms.length <= 1000`
• `0 <= rooms[i].length <= 1000`
• The number of keys in all rooms combined is at most `3000`.

#### Idea:

(Jump to: Problem Description || Code: JavaScript | Python | Java | C++)

Since we can only enter rooms to which we have found a key, we can't just iterate through the entire input array (R) normally. If we think of this like a graph problem, we can see that the rooms are like nodes and the keys are like edges.

In that case, we can use a breadth-first search (BFS) queue or a depth-first search (DFS) stack approach, or even a DFS recursion approach here to good effect. Here, we'll push newly found keys onto stack as we go through.

To eliminate duplicate stack entries, we can use a lightweight boolean array (vis) to keep track of which rooms have already been pushed onto the stack. Rather than having to count the number of visited rooms again at the end, we can just use another variable (count) to keep track of that separately.

Once our stack runs empty, we can just check to see if the count is the same as the length of R and return the answer.

#### Implementation:

Javascript can use a Uint8Array instead of a boolean array.

#### Javascript Code:

``````var canVisitAllRooms = function(R) {
let vis = new Uint8Array(R.length), stack = [0], count = 1
vis[0] = 1
while (stack.length) {
let keys = R[stack.pop()]
for (let k of keys)
if (!vis[k]) stack.push(k), vis[k] = 1, count++
}
return R.length === count
};
``````

#### Python Code:

``````class Solution:
def canVisitAllRooms(self, R: List[List[int]]) -> bool:
vis, stack, count = [False for _ in range(len(R))], [0], 1
vis[0] = 1
while stack:
keys = R[stack.pop()]
for k in keys:
if not vis[k]:
stack.append(k)
vis[k] = True
count += 1
return len(R) == count
``````

#### Java Code:

``````class Solution {
public boolean canVisitAllRooms(List<List<Integer>> R) {
boolean[] vis = new boolean[R.size()];
vis[0] = true;
Stack<Integer> stack = new Stack<>();
stack.push(0);
int count = 1;
while (stack.size() > 0)
for (int k : R.get(stack.pop()))
if (!vis[k]) {
stack.push(k);
vis[k] = true;
count++;
}
return R.size() == count;
}
}
``````

#### C++ Code:

``````class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& R) {
vector<bool> vis(R.size(), false);
vis[0] = true;
stack<int> stk = stack<int>({0});
int count = 1;
while (stk.size()) {
vector<int> keys = R[stk.top()]; stk.pop();
for (int k : keys)
if (!vis[k]) stk.push(k), vis[k] = true, count++;
}
return R.size() == count;
}
};
``````