Appearance
0841-钥匙和房间
https://leetcode.cn/problems/keys-and-rooms
有 n 个房间,房间按从 0 到 n - 1 编号。最初,除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而,你不能在没有获得钥匙的时候进入锁住的房间。 当你进入一个房间,你可能会在里面找到一套不同的钥匙,每把钥匙上都有对应的房间号,即表示钥匙可以打开的房间。你可以拿上所有钥匙去解锁其他房间。 给你一个数组 rooms 其中 rooms[i] 是你进入 i 号房间可以获得的钥匙集合。如果能进入 所有 房间返回 true,否则返回 false。
示例 1:
输入:rooms = [[1],[2],[3],[]]
输出:true
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。
示例 2:
输入:rooms = [[1,3],[3,0,1],[2],[0]]
输出:false
解释:我们不能进入 2 号房间。
提示:
- n == rooms.length
- 2 <= n <= 1000
- 0 <= rooms[i].length <= 1000
- 1 <= sum(rooms[i].length) <= 3000
- 0 <= rooms[i][j] < n
- 所有 rooms[i] 的值 互不相同
思路
统计 入度,最后找出 入度为 0 的数据,表示不能进入那个房间
注意:
- 如果那个房间只放了自己的钥匙,则不能打开自己
- 如果两个钥匙循环放入两个房间了,则也是互相不能打开
- 递归的时候,如果房间已经打开,就不用重新去打开,否则会出现不停循环,堆栈溢出
参考代码
csharp
public class Solution {
int[] ingress;
private void UnlockRooms(IList<IList<int>> rooms, int index){
if(ingress[index] == 0){
//解锁房间
ingress[index] = 1;
//拿到钥匙解锁其他房间
for(int j=0; j<rooms[index].Count; j++){
UnlockRooms(rooms,rooms[index][j]);
}
}
}
public bool CanVisitAllRooms(IList<IList<int>> rooms) {
int n = rooms.Count;
ingress = new int[n];
UnlockRooms(rooms,0);
//寻找结果为0的房间,表示不能打开
for(int i=0; i<n; i++){
if(ingress[i] == 0){
return false;
}
}
return true;
}
}
思路2 【官方,广度优先搜索】
从第一个节点开始,广度优先搜索,通过钥匙访问每个房间,并且记录是否已经访问过 统计最后的访问房间数是否等于总数
通过 BFS 模拟访问顺序,访问过的不再继续访问
csharp
public class Solution {
public bool CanVisitAllRooms(IList<IList<int>> rooms) {
int n = rooms.Count;
int[] visited = new int[n];
Queue<int> myQueue = new Queue<int>();
myQueue.Enqueue(0);
int num = 0;
while(myQueue.Count > 0){
int count = myQueue.Count;
for(int i=0; i<count; i++){
int roomNumber = myQueue.Dequeue();
if(visited[roomNumber] == 0){
visited[roomNumber] = 1;
num++;
foreach(int key in rooms[roomNumber]){
myQueue.Enqueue(key);
}
}
}
}
return num == n;
}
}
复习:20220703
csharp
public class Solution {
private bool[] ingress;
private void dfs(IList<IList<int>> rooms, int room){
if(!ingress[room]){
ingress[room] = true;
//遍历key
foreach(int key in rooms[room]){
dfs(rooms, key);
}
}
}
public bool CanVisitAllRooms(IList<IList<int>> rooms) {
int n = rooms.Count;
ingress = new bool[n];
dfs(rooms,0);
for(int i=0; i<ingress.Length; i++){
if(ingress[i] == false){
return false;
}
}
return true;
}
}
AlgoPress