Solution: Keys and Rooms
Tags: algorithms, javascript, java, python
Published: 2021-03-19 09:01:07

*This is part of a series of Leetcode solution explanations ([index](https://dev.to/seanpgallivan/leetcode-solutions-index-57fl)). If you liked this solution or found it useful,* ***please like*** *this post and/or* ***upvote*** *[my solution post on Leetcode's forums](https://leetcode.com/problems/keys-and-rooms/discuss/1116707).*

---

#### [Leetcode Problem #841 (*Medium*): Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/)

---

#### ***Description:***

<br />(*Jump to*: [*Solution Idea*](#idea) || *Code*: [*JavaScript*](#javascript-code) | [*Python*](#python-code) | [*Java*](#java-code) | [*C++*](#c-code))

>
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.<br>We then go to room 1, and pick up key 2.<br>We then go to room 2, and pick up key 3.<br>We then go to room 3.<br>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:***

<br />(*Jump to*: [*Problem Description*](#description) || *Code*: [*JavaScript*](#javascript-code) | [*Python*](#python-code) | [*Java*](#java-code) | [*C++*](#c-code))

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:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```javascript
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:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```python
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:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```java
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:***
<br />(*Jump to*: [*Problem Description*](#description) || [*Solution Idea*](#idea))
```c++
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;
    }
};
```