DEV Community

loading...
Cover image for Solution: Keys and Rooms

Solution: Keys and Rooms

seanpgallivan
Fledgling software developer; the struggle is a Rational Approximation.
・3 min read

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 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:


(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
};
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
};
Enter fullscreen mode Exit fullscreen mode

Discussion (0)