-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathkeys_and_rooms.dart
152 lines (125 loc) · 3.63 KB
/
keys_and_rooms.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
-* 841. Keys and Rooms *-
There are n rooms labeled from 0 to n - 1 and all the rooms are locked except for room 0. Your goal is to visit all the rooms. However, you cannot enter a locked room without having its key.
When you visit a room, you may find a set of distinct keys in it. Each key has a number on it, denoting which room it unlocks, and you can take all of them with you to unlock the other rooms.
Given an array rooms where rooms[i] is the set of keys that you can obtain if you visited room i, return true if you can visit all the rooms, or false otherwise.
Example 1:
Input: rooms = [[1],[2],[3],[]]
Output: true
Explanation:
We visit room 0 and pick up key 1.
We then visit room 1 and pick up key 2.
We then visit room 2 and pick up key 3.
We then visit room 3.
Since we were able to visit every room, we return true.
Example 2:
Input: rooms = [[1,3],[3,0,1],[2],[0]]
Output: false
Explanation: We can not enter room number 2 since the only key that unlocks it is in that room.
Constraints:
n == rooms.length
2 <= n <= 1000
0 <= rooms[i].length <= 1000
1 <= sum(rooms[i].length) <= 3000
0 <= rooms[i][j] < n
All the values of rooms[i] are unique.
*/
/*
*/
import 'dart:collection';
class A {
bool canVisitAllRooms(List<List<int>> rooms) {
if (rooms.length == 0) return true;
List<bool> visited = List.filled(rooms.length, false);
depthFirstSearch(0, rooms, visited);
for (int i = 0; i < rooms.length; i++) if (!visited[i]) return false;
return true;
}
void depthFirstSearch(int index, List<List<int>> rooms, List<bool> visited) {
visited[index] = true;
for (int n in rooms[index]) {
if (!visited[n]) {
depthFirstSearch(n, rooms, visited);
}
}
}
}
class B {
// breath first Search
bool canVisitAllRooms(List<List<int>> rooms) {
HashSet<int> visited = HashSet();
Queue<int> queue = Queue();
queue.add(0);
visited.add(0);
while (queue.isNotEmpty) {
// poll
int node = queue.removeFirst();
for (int next in rooms[node]) {
if (!visited.contains(next)) {
queue.add(next);
visited.add(next);
}
}
}
return visited.length == rooms.length;
}
}
class C {
bool canVisitAllRooms(List<List<int>> rooms) {
// sanity check
if (rooms.isEmpty || rooms.length == 0) {
return false;
}
UnionFind uf = UnionFind(rooms.length);
for (int i = 0; i < rooms.length; ++i) {
for (int j = 0; j < rooms[i].length; ++j) {
uf.union(i, rooms[i][j]);
}
}
return uf.count == 1; // means only one connected component
}
}
class UnionFind {
late List<int> ids;
late List<int> sizes;
late int count; // represents the number of connected component
UnionFind(int capacity) {
ids = List.filled(capacity, 0);
sizes = List.filled(capacity, 0);
count = capacity;
for (int i = 0; i < capacity; ++i) {
ids[i] = i;
sizes[i] = 1;
}
}
void union(int a, int b) {
int rootOfa = find(a);
int rootOfb = find(b);
if (rootOfa == rootOfb) {
// already in the same connected component
return;
}
count--; // union them, so decrease count
if (sizes[rootOfa] >= sizes[rootOfb]) {
// apply weighted union
ids[rootOfb] = rootOfa;
sizes[rootOfa] += sizes[rootOfb];
} else {
ids[rootOfa] = rootOfb;
sizes[rootOfb] += sizes[rootOfa];
}
}
int find(int a) {
int root = ids[a];
while (root != ids[root]) {
root = ids[root];
}
while (root != ids[a]) {
// apply path compression
int parent = ids[a];
ids[a] = root;
a = parent;
}
return root;
}
}