題目鏈接
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:
輸入: [[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。
解題思路
1.DFS
我們可以使用深度優先搜索的方式遍歷整張圖,統計可以到達的節點個數,並利用數組vis
標記當前節點是否訪問過,以防止重複訪問。注意本題是不需要回溯的!
2.BFS
我們也可以使用廣度優先搜索的方式遍歷整張圖,統計可以到達的節點個數,並利用數組vis
標記當前節點是否訪問過,以防止重複訪問。
- 利用set記錄被訪問的房間的個數,如果剛好等於所有被訪問的房間,爲true,否則爲false
- 當房間被訪問過,就不再添加房間進set,初始化時,將0號房間加入到set中
AC代碼
1.DFS
class Solution {
Set<Integer> st = new HashSet<>();
void dfs(int num,List<List<Integer>> rooms,int[] view){
if(view[num] == 1) return;
List<Integer> temp = new LinkedList<>();
temp = rooms.get(num);
view[num] = 1;
st.add(num);
for(int i = 0; i < temp.size(); i++) dfs(temp.get(i),rooms,view);
}
public boolean canVisitAllRooms(List<List<Integer>> rooms) {
if(rooms.size()==0 || rooms.size()==1) return true;
int[] view = new int[rooms.size()];
dfs(0,rooms,view);
if(st.size()==rooms.size())return true;
else return false;
}
}
2.BFS
public boolean canVisitAllRooms(List<List<Integer>> rooms) {
Set<Integer> set = new HashSet<>();
Queue<Integer> queue = new LinkedList<>();
int n = rooms.size();
List<Integer> zeroRoom = rooms.get(0);
set.add(0);
for (int i : zeroRoom) {
queue.offer(i);
set.add(i);
}
while (!queue.isEmpty()) {
int curr = queue.poll();
List<Integer> currRoom = rooms.get(curr);
for (int c : currRoom) {
if (!set.contains(c)) {
queue.offer(c);
set.add(c);
}
}
}
return set.size() == n;
}