图解题库 / 图 · DFS

841. 钥匙和房间

中等 含交互动画

学完这道你应该能: 说清它为什么用「DFS」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

每个房间里有若干钥匙(通往别的房间)。从 0 号房开始,能否访问到所有房间?

rooms = [[1], [2], [3], []]
输出 = true

思路解析

把房间看成节点、钥匙看成有向边。从 0 开始 DFS,用一个 visited 记下哪些房间去过了。最后数一下 visited,等于房间总数就 true。

建图 · 从 0 出发:先画成图,房间就是节点。从 0 进去,标记成已访问(图上变绿)。它手里有把钥匙,能去 1 号房。

用 0 的钥匙 → 访问 1:拿 0 的钥匙去开 1 的门,进去标记已访问。1 房里又有钥匙,指向 2。

→ 访问 2:再用 1 的钥匙开 2,标记已访问。2 房也有钥匙,能去 3。

→ 访问 3 · 全到齐:开到 3,标记。3 房没钥匙了,这条路走到头。

判断:数一下去过的房间:4 个,正好等于总数,说明全都能到,返回 true。要是有房间没去过,就返回 false。

凡是「从一个点出发能不能走到所有点」「有几个连通块」这种,都能用 DFS/BFS 数可达节点。钥匙房间、被围住的区域、省份数量,都是这一类。

参考代码(Python)

Python
1visited = set()
2def dfs(room):
3    visited.add(room)
4    for key in rooms[room]:           # 房里的每把钥匙
5        if key not in visited:        # 没去过的房间
6            dfs(key)
7dfs(0)
8return len(visited) == len(rooms)

复杂度分析

  • 时间复杂度:O(N+E) —— 房间数 + 钥匙总数
  • 空间复杂度:O(N) —— visited + 递归栈

套路模板

模板背下来:visited 标记、邻居只递归没去过的、最后数一下 visited。把递归换成队列,就是 BFS,效果一样。

Python
1visited = set()
2def dfs(u):
3    visited.add(u)
4    for v in graph[u]:
5        if v not in visited: dfs(v)   # 只走没访问的
6dfs(start)
7# len(visited) == N ? 全连通

易错点

  • 进 dfs 不立刻标记 → ✅ 一进入就加 visited(否则有环时会无限递归)
  • 判断只看"有没有走到终点" → ✅ 比对 len(visited)==N(题目要的是访问到全部房间)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →605. 种花问题 ← 返回题库