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.
Leetcode Problem #841 (Medium): Keys and Rooms
Description:
(Jump to: Solution Idea || Code: JavaScript | Python | Java | C++)
There are
N
rooms and you start in room0
. Each room has a distinct number in0, 1, 2, ..., N-1
, and each room may have some keys to access the next room.Formally, each room
i
has a list of keysrooms[i]
, and each keyrooms[i][j]
is an integer in[0, 1, ..., N-1]
whereN = rooms.length
. A keyrooms[i][j] = v
opens the room with numberv
.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:
(Jump to: Problem Description || Solution Idea)
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:
(Jump to: Problem Description || Solution Idea)
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:
(Jump to: Problem Description || Solution Idea)
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:
(Jump to: Problem Description || Solution Idea)
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;
}
};
Top comments (0)