There are n rooms labeled from 0 to n - 1 and all the rooms are locked except for room 0. Your goal is to visit all the rooms. However, you cannot enter a locked room without having its key.
When you visit a room, you may find a set of distinct keys in it. Each key has a number on it, denoting which room it unlocks, and you can take all of them with you to unlock the other rooms.
Given an array rooms where rooms[i] is the set of keys that you can obtain if you visited room i, return true if you can visit all the rooms, or false otherwise.
Example 1:
Input: rooms = [[1],[2],[3],[]] Output: true Explanation: We visit room 0 and pick up key 1. We then visit room 1 and pick up key 2. We then visit room 2 and pick up key 3. We then visit room 3. Since we were able to visit every room, we return true.
Example 2:
Input: rooms = [[1,3],[3,0,1],[2],[0]] Output: false Explanation: We can not enter room number 2 since the only key that unlocks it is in that room.
Constraints:
n == rooms.length2 <= n <= 10000 <= rooms[i].length <= 10001 <= sum(rooms[i].length) <= 30000 <= rooms[i][j] < nrooms[i] are unique.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to the keys and rooms problem involves trying every possible path through the rooms. We start at the first room and explore all the keys we find to unlock other rooms. We repeat this process, exploring new rooms as we unlock them, until we have either visited all rooms or run out of new rooms to explore.
Here's how the algorithm would work step-by-step:
def canVisitAllRooms(rooms):
number_of_rooms = len(rooms)
visited_rooms = [False] * number_of_rooms
visited_rooms[0] = True
rooms_to_visit = [0]
while rooms_to_visit:
current_room = rooms_to_visit.pop(0)
# Iterate through the keys in the current room.
for key in rooms[current_room]:
# Avoid infinite loops by visiting each room only once.
if not visited_rooms[key]:
visited_rooms[key] = True
# Queue up the newly unlocked room for exploration
rooms_to_visit.append(key)
# Check if all rooms have been visited.
return all(visited_rooms)The goal is to determine if you can unlock all rooms, starting from room 0. We can think of this as exploring a maze where each room contains keys to other rooms. We'll use a method similar to how you might explore a real maze, marking off the rooms you've already been to so you don't waste time going in circles.
Here's how the algorithm would work step-by-step:
def can_visit_all_rooms(rooms):
number_of_rooms = len(rooms)
visited_rooms = [False] * number_of_rooms
# Start from room 0
visited_rooms[0] = True
rooms_to_visit = [0]
while rooms_to_visit:
current_room = rooms_to_visit.pop()
# Explore keys in the current room
for key in rooms[current_room]:
# Visit unvisited rooms
if not visited_rooms[key]:
visited_rooms[key] = True
rooms_to_visit.append(key)
#Check if all rooms were visited
return all(visited_rooms)| Case | How to Handle |
|---|---|
| rooms is null or empty | Return true immediately, as there are no rooms to visit, fulfilling the condition trivially. |
| rooms contains only one room with no keys | Return true, because we start in room 0, which is the only room. |
| A room's key list is empty | The algorithm should still function correctly, as the empty key list simply means we don't unlock any new rooms from that room. |
| Rooms contain cycles (e.g., room A has key to B, room B has key to A) | The visited set prevents infinite loops by tracking visited rooms. |
| Rooms are unreachable from room 0 | The algorithm correctly identifies that not all rooms can be visited and returns false. |
| Maximum number of rooms to test scalability | The solution's time complexity, O(N+E) where N is the number of rooms and E is the number of keys (edges), makes it relatively scalable. |
| A room contains a key to itself | The algorithm correctly ignores this self-referential key by using a visited set. |
| Integer overflow if key values are very large, but within integer range | Keys represent room indices, so overflow isn't directly applicable since we're not performing arithmetic with them beyond indexing into the rooms array. |