Skip to content

Commit 0d4ffea

Browse files
committed
leetcode
1 parent 3efedb4 commit 0d4ffea

File tree

3 files changed

+283
-0
lines changed

3 files changed

+283
-0
lines changed

KeysAndRooms/keys_and_rooms.dart

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

KeysAndRooms/keys_and_rooms.md

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# 🔥 Keys and Rooms 🔥 || 3 Approaches || Simple Fast and Easy || with Explanation
2+
3+
## Idea
4+
5+
Since we can only enter rooms to which we have found a key, we can't just iterate through the entire input array (R) normally. If we think of this like a graph problem, we can see that the rooms are like nodes and the keys are like edges.
6+
7+
In that case, we can use a breadth-first search (BFS) queue or a depth-first search (DFS) stack approach, or even a DFS recursion approach here to good effect. Here, we'll push newly found keys onto stack as we go through.
8+
9+
To eliminate duplicate stack entries, we can use a lightweight boolean array (vis) to keep track of which rooms have already been pushed onto the stack. Rather than having to count the number of visited rooms again at the end, we can just use another variable (count) to keep track of that separately.
10+
11+
Once our stack runs empty, we can just check to see if the count is the same as the length of R and return the answer.
12+
13+
## Solution - 1
14+
15+
```dart
16+
class Solution {
17+
bool canVisitAllRooms(List<List<int>> rooms) {
18+
if (rooms.length == 0) return true;
19+
List<bool> visited = List.filled(rooms.length, false);
20+
depthFirstSearch(0, rooms, visited);
21+
for (int i = 0; i < rooms.length; i++) if (!visited[i]) return false;
22+
return true;
23+
}
24+
25+
void depthFirstSearch(int index, List<List<int>> rooms, List<bool> visited) {
26+
visited[index] = true;
27+
for (int n in rooms[index]) {
28+
if (!visited[n]) {
29+
depthFirstSearch(n, rooms, visited);
30+
}
31+
}
32+
}
33+
}
34+
```
35+
36+
## Solution - 2 Breadth First Search
37+
38+
```dart
39+
import 'dart:collection';
40+
41+
class Solution {
42+
bool canVisitAllRooms(List<List<int>> rooms) {
43+
HashSet<int> visited = HashSet();
44+
Queue<int> queue = Queue();
45+
queue.add(0);
46+
visited.add(0);
47+
while (queue.isNotEmpty) {
48+
int node = queue.removeFirst();
49+
for (int next in rooms[node]) {
50+
if (!visited.contains(next)) {
51+
queue.add(next);
52+
visited.add(next);
53+
}
54+
}
55+
}
56+
return visited.length == rooms.length;
57+
}
58+
}
59+
```
60+
61+
## Solution - 3 Union Find Algorithm
62+
63+
### WARNING - Some of cases will fail but it is intreating implementation
64+
65+
```dart
66+
class Solution {
67+
bool canVisitAllRooms(List<List<int>> rooms) {
68+
// sanity check
69+
if (rooms.isEmpty || rooms.length == 0) {
70+
return false;
71+
}
72+
UnionFind uf = UnionFind(rooms.length);
73+
for (int i = 0; i < rooms.length; ++i) {
74+
for (int j = 0; j < rooms[i].length; ++j) {
75+
uf.union(i, rooms[i][j]);
76+
}
77+
}
78+
return uf.count == 1; // means only one connected component
79+
}
80+
}
81+
```
82+
83+
```dart
84+
85+
class UnionFind {
86+
late List<int> ids;
87+
late List<int> sizes;
88+
late int count; // represents the number of connected component
89+
UnionFind(int capacity) {
90+
ids = List.filled(capacity, 0);
91+
sizes = List.filled(capacity, 0);
92+
count = capacity;
93+
for (int i = 0; i < capacity; ++i) {
94+
ids[i] = i;
95+
sizes[i] = 1;
96+
}
97+
}
98+
void union(int a, int b) {
99+
int rootOfa = find(a);
100+
int rootOfb = find(b);
101+
if (rootOfa == rootOfb) {
102+
// already in the same connected component
103+
return;
104+
}
105+
count--; // union them, so decrease count
106+
if (sizes[rootOfa] >= sizes[rootOfb]) {
107+
// apply weighted union
108+
ids[rootOfb] = rootOfa;
109+
sizes[rootOfa] += sizes[rootOfb];
110+
} else {
111+
ids[rootOfa] = rootOfb;
112+
sizes[rootOfb] += sizes[rootOfa];
113+
}
114+
}
115+
116+
int find(int a) {
117+
int root = ids[a];
118+
while (root != ids[root]) {
119+
root = ids[root];
120+
}
121+
while (root != ids[a]) {
122+
// apply path compression
123+
int parent = ids[a];
124+
ids[a] = root;
125+
a = parent;
126+
}
127+
return root;
128+
}
129+
}
130+
```

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ This repo contain leetcode solution using DART and GO programming language. Most
171171
- [**150.** Evaluate Reverse Polish Notation](EvaluateReversePolishNotation/evaluate_reverse_polish_notation.dart)
172172
- [**739.** Daily Temperatures](DailyTemperatures/daily_temperatures.dart)
173173
- [**1971.* Find if Path Exists in Graph](FindIfPathExistsInGraph/find_if_path_exists_in_graph.dart)
174+
- [**841.** Keys and Rooms](KeysAndRooms/keys_and_rooms.dart)
174175

175176
## Reach me via
176177

0 commit comments

Comments
 (0)