DFS_leetcode.841.钥匙和房间

🌸题目

🍁有 N 个房间,开始时你位于 0 号房间。每个房间有不同的号码:0,1,2,…,N-1,并且房间里可能有一些钥匙能使你进入下一个房间。

在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j][0,1,...,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。

最初,除 0 号房间外的其余所有房间都被锁住。

你可以自由地在房间之间来回走动。

如果能进入每个房间返回 true,否则返回 false

示例:

1
2
3
4
5
6
7
8
输入: [[1],[2],[3],[]]
输出: true
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。

示例2

1
2
3
输入:[[1,3],[3,0,1],[2],[0]]
输出:false
解释:我们不能进入 2 号房间。

提示:

  1. 1 <= rooms.length <= 1000
  2. 0 <= rooms[i].length <= 1000
  3. 所有房间中的钥匙数量总计不超过 3000

🌸分析

当 x 号房间中有 y号房间的钥匙时,我们就可以从 xx 号房间去往 y 号房间。如果我们将这 n 个房间看成有向图中的 n 个节点,那么上述关系就可以看作是图中的x号点到 y 号点的一条有向边。

这样一来,问题就变成了给定一张有向图,询问从 0 号节点出发是否能够到达所有的节点。

🌸解法一:DFS

我们可以使用深度优先搜索的方式遍历整张图,统计可以到达的节点个数,并利用数组vis 标记当前节点是否访问过,以防止重复访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
boolean[] vis;
int num;

public boolean canVisitAllRooms(List<List<Integer>> rooms) {
int n = rooms.size();
num = 0;
vis = new boolean[n];
dfs(rooms, 0);
return num == n;
}

public void dfs(List<List<Integer>> rooms, int x) {
vis[x] = true;
num++;
for (int it : rooms.get(x)) {
if (!vis[it]) {
dfs(rooms, it);
}
}
}
}

python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
def dfs(x: int):
vis.add(x)
nonlocal num
num += 1
for it in rooms[x]:
if it not in vis:
dfs(it)

n = len(rooms)
num = 0
vis = set()
dfs(0)
return num == n
  • 时间复杂度:O(n+m),其中 n 是房间的数量,m 是所有房间中的钥匙数量的总数。

  • 空间复杂度:O(n),其中 n 是房间的数量。主要为栈空间的开销。

🌸解法二: BFS

我们也可以使用广度优先搜索的方式遍历整张图,统计可以到达的节点个数,并利用数组 vis 标记当前节点是否访问过,以防止重复访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public boolean canVisitAllRooms(List<List<Integer>> rooms) {
int n = rooms.size(), num = 0;
boolean[] vis = new boolean[n];
Queue<Integer> que = new LinkedList<Integer>();
vis[0] = true;
que.offer(0);
while (!que.isEmpty()) {
int x = que.poll();
num++;
for (int it : rooms.get(x)) {
if (!vis[it]) {
vis[it] = true;
que.offer(it);
}
}
}
return num == n;
}
}

python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
n = len(rooms)
num = 0
vis = {0}
que = collections.deque([0])

while que:
x = que.popleft()
num += 1
for it in rooms[x]:
if it not in vis:
vis.add(it)
que.append(it)

return num == n
  • 时间复杂度:O(n+m),其中 n 是房间的数量,m 是所有房间中的钥匙数量的总数。

  • 空间复杂度:O(n),其中 n 是房间的数量。主要为队列的开销。

最后,不经历风雨,怎能在计算机的大山之顶看见彩虹呢! 无论怎样,相信明天一定会更好!!!!!

-------------本文结束感谢您的阅读-------------
云澈 wechat
扫一扫,用手机访问哦
坚持原创技术分享,您的支持将鼓励我继续创作!
0%