841.Keys and Rooms === ###### tags: `Medium`,`DFS`,`BFS`,`Graph` [841. Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/) ### 題目描述 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.length` * 2 <= `n` <= 1000 * 0 <= `rooms[i].length` <= 1000 * 1 <= `sum(rooms[i].length)` <= 3000 * 0 <= `rooms[i][j]` < n * All the values of `rooms[i]` are **unique**. ### 解答 #### C# ```csharp= public class Solution { public bool CanVisitAllRooms(IList<IList<int>> rooms) { bool[] unlocked = new bool[rooms.Count]; unlocked[0] = true; Stack<int> roomKeys = new(); roomKeys.Push(0); while (roomKeys.Count > 0) { int roomKey = roomKeys.Pop(); foreach(int key in rooms[roomKey]) { if (!unlocked[key]) { unlocked[key] = true; roomKeys.Push(key); } } } return unlocked.All(unlock => unlock); } } ``` >[name=Jim][time=Dec 20, 2022] #### Javascript ```javascript= function canVisitAllRooms(rooms) { const visited = new Array(rooms.length).fill(false); const stack = [0]; while (stack.length) { const current = stack.pop(); if (visited[current]) continue; visited[current] = true; stack.push(...rooms[current]); } for (let i = 0; i < rooms.length; i++) { if (!visited[i]) return false; } return true; } ``` 用Set寫了一個,感覺比較簡潔,但不會比較快。 ```javascript= function canVisitAllRooms2(rooms) { const stack = [0]; const visited = new Set(); while (stack.length) { const current = stack.pop(); if (visited.has(current)) continue; visited.add(current); stack.push(...rooms[current]); } return visited.size === rooms.length; } ``` >[name=Marsgoat][time=Dec 20, 2022] #### Python ```python= class Solution: def canVisitAllRooms(self, rooms: List[List[int]]) -> bool: self.keys = {0} self.visited = set() def dfs(idx): for i in range(len(rooms)): if i in self.keys and i not in self.visited: if i != 0 and i == idx: continue self.visited.add(i) for key in rooms[i]: self.keys.add(key) dfs(i + 1) dfs(0) return len(self.visited) == len(rooms) ``` >[name=Kobe][time=Dec 20, 2022] ```python= class Solution: def canVisitAllRooms(self, rooms: List[List[int]]) -> bool: keys = set() keys.add(0) room_done = set() while len(keys-room_done) > 0: for room in keys-room_done: for key in rooms[room]: keys.add(key) room_done.add(room) return len(room_done) == len(rooms) ``` >[name=gp][time=Dec 20, 2022] ```python= class Solution: def canVisitAllRooms(self, rooms: List[List[int]]) -> bool: keys = [0] used_key = set() while len(keys) and len(used_key) != len(rooms): current_key = keys.pop() if current_key in used_key: continue keys = rooms[current_key] + keys used_key.add(current_key) #print(used_key) if len(used_key) != len(rooms): return False return True ``` >[name=玉山][time=Dec 21, 2022] ### Reference [回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)