题目描述
有 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:
输入: [[1], [2], [3], []]
输出: true
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。
示例 2:
输入:[[1, 3], [3, 0, 1], [2], [0]]
输出:false
解释:我们不能进入 2 号房间。
提示:
- 1 <= rooms.length <= 1000
- 0 <= rooms[i].length <= 1000
- 所有房间中的钥匙数量总计不超过 3000。
深度优先搜索
此题我们将房间理解成节点,房间 A 到房间 B 理解成边,这样这道题就变成了,我们从图的 0 点出发,能否到达所有节点的问题。
具体实现上,我们使用一个变量 count 记录访问过的房间数,每次访问过一个房间后就标记为访问过 visited[room] = true
,并将 count++
,如果最后 count 等于房间的数量,那么就说明可以访问所有的房间。
1 | int count = 0; |
复杂度分析
- 时间复杂度:O(n + m),其中 n 是房间的数量,m 是所有房间中的钥匙数量的总数。
- 空间复杂度:O(n),其中 n 是房间的数量。主要为栈空间的开销。
广度优先搜索
同样的,我们可以使用广度优先搜索解决此问题。
1 | public boolean canVisitAllRooms(List<List<Integer>> rooms) { |
复杂度分析
- 时间复杂度:O(n + m),其中 n 是房间的数量,m 是所有房间中的钥匙数量的总数。
- 空间复杂度:O(n),其中 n 是房间的数量。主要为队列的开销。
来源
文章标题:钥匙和房间
文章作者:cylong
文章链接:https://0skyu.cn/posts/1da7.html
有问题或者建议欢迎在下方评论。欢迎转载、引用,但希望标明出处,感激不尽(●’◡’●)
- 本文标题:钥匙和房间
- 创建时间:2020-08-31 23:50:07
- 本文链接:posts/1da7.html
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!