Skip to content

Commit ef0c0dd

Browse files
committed
feat: add solutions to lc problem: No.0749
No.0749.Contain Virus
1 parent b0435d6 commit ef0c0dd

File tree

7 files changed

+651
-4
lines changed

7 files changed

+651
-4
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173

174174
感谢以下所有朋友对本项目的贡献!
175175

176-
<a href="https://github.com/doocs/leetcode/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=doocs/leetcode&max=500" /></a>
176+
<a href="https://github.com/doocs/leetcode/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=doocs/leetcode&max=499" /></a>
177177

178178
## 赞助者
179179

README_EN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ You can also contribute to [doocs/leetcode](https://github.com/doocs/leetcode) u
165165

166166
This project exists thanks to all the people who contribute.
167167

168-
<a href="https://github.com/doocs/leetcode/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=doocs/leetcode&max=500" /></a>
168+
<a href="https://github.com/doocs/leetcode/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=doocs/leetcode&max=499" /></a>
169169

170170
## Backers & Sponsors
171171

solution/0700-0799/0749.Contain Virus/README.md

+224-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<strong>输出:</strong> 10
2626
<strong>解释:</strong>一共有两块被病毒感染的区域。
2727
在第一天,添加 5 墙隔离病毒区域的左侧。病毒传播后的状态是:
28-
<img src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/0700-0799/0749.Contain%20Virus/images/653" />
28+
<img src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/0700-0799/0749.Contain%20Virus/images/virus12edited-grid.jpg" />
2929
第二天,在右侧添加 5 个墙来隔离病毒区域。此时病毒已经被完全控制住了。
3030
<img src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/0700-0799/0749.Contain%20Virus/images/virus13edited-grid.jpg" style="height: 261px; width: 500px;" />
3131
</pre>
@@ -67,22 +67,244 @@
6767

6868
<!-- 这里可写通用的实现逻辑 -->
6969

70+
**方法一:DFS 暴力模拟**
71+
72+
DFS 找到每个病毒区域 `areas[i]`,同时记录每个区域边界节点 `boundaries[i]` 以及周长 `c[i]`
73+
74+
接着对威胁最大的病毒区域进行隔离,累加所需的防火墙数量。
75+
76+
剩余的病毒区域向外感染一个区域。
77+
7078
<!-- tabs:start -->
7179

7280
### **Python3**
7381

7482
<!-- 这里可写当前语言的特殊实现逻辑 -->
7583

7684
```python
77-
85+
class Solution:
86+
def containVirus(self, isInfected: List[List[int]]) -> int:
87+
def dfs(i, j):
88+
vis[i][j] = True
89+
areas[-1].add((i, j))
90+
for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]:
91+
x, y = i + a, j + b
92+
if 0 <= x < m and 0 <= y < n:
93+
if isInfected[x][y] == 1 and not vis[x][y]:
94+
dfs(x, y)
95+
elif isInfected[x][y] == 0:
96+
c[-1] += 1
97+
boundaries[-1].add((x, y))
98+
99+
m, n = len(isInfected), len(isInfected[0])
100+
ans = 0
101+
while 1:
102+
vis = [[False] * n for _ in range(m)]
103+
areas = []
104+
c = []
105+
boundaries = []
106+
for i, row in enumerate(isInfected):
107+
for j, v in enumerate(row):
108+
if v == 1 and not vis[i][j]:
109+
areas.append(set())
110+
boundaries.append(set())
111+
c.append(0)
112+
dfs(i, j)
113+
if not areas:
114+
break
115+
idx = boundaries.index(max(boundaries, key=len))
116+
ans += c[idx]
117+
for k, area in enumerate(areas):
118+
if k == idx:
119+
for i, j in area:
120+
isInfected[i][j] = -1
121+
else:
122+
for i, j in area:
123+
for a, b in [[0, -1], [0, 1], [1, 0], [-1, 0]]:
124+
x, y = i + a, j + b
125+
if 0 <= x < m and 0 <= y < n and isInfected[x][y] == 0:
126+
isInfected[x][y] = 1
127+
return ans
78128
```
79129

80130
### **Java**
81131

82132
<!-- 这里可写当前语言的特殊实现逻辑 -->
83133

84134
```java
135+
class Solution {
136+
private static final int[] DIRS = {-1, 0, 1, 0, -1};
137+
private List<Integer> c = new ArrayList<>();
138+
private List<Set<Integer>> areas = new ArrayList<>();
139+
private List<Set<Integer>> boundaries = new ArrayList<>();
140+
private int[][] isInfected;
141+
private int m;
142+
private int n;
143+
144+
public int containVirus(int[][] isInfected) {
145+
m = isInfected.length;
146+
n = isInfected[0].length;
147+
this.isInfected = isInfected;
148+
int ans = 0;
149+
while (true) {
150+
boolean[][] vis = new boolean[m][n];
151+
areas.clear();
152+
c.clear();
153+
boundaries.clear();
154+
for (int i = 0; i < m; ++i) {
155+
for (int j = 0; j < n; ++j) {
156+
if (isInfected[i][j] == 1 && !vis[i][j]) {
157+
areas.add(new HashSet<>());
158+
boundaries.add(new HashSet<>());
159+
c.add(0);
160+
dfs(i, j, vis);
161+
}
162+
}
163+
}
164+
if (boundaries.isEmpty()) {
165+
break;
166+
}
167+
int idx = max(boundaries);
168+
ans += c.get(idx);
169+
for (int t = 0; t < areas.size(); ++t) {
170+
if (t == idx) {
171+
for (int v : areas.get(t)) {
172+
int i = v / n, j = v % n;
173+
isInfected[i][j] = -1;
174+
}
175+
} else {
176+
for (int v : areas.get(t)) {
177+
int i = v / n, j = v % n;
178+
for (int k = 0; k < 4; ++k) {
179+
int x = i + DIRS[k], y = j + DIRS[k + 1];
180+
if (x >= 0 && x < m && y >= 0 && y < n && isInfected[x][y] == 0) {
181+
isInfected[x][y] = 1;
182+
}
183+
}
184+
}
185+
}
186+
}
187+
188+
}
189+
return ans;
190+
}
191+
192+
private int max(List<Set<Integer>> boundaries) {
193+
int idx = 0;
194+
int mx = boundaries.get(0).size();
195+
for (int i = 1; i < boundaries.size(); ++i) {
196+
int t = boundaries.get(i).size();
197+
if (mx < t) {
198+
mx = t;
199+
idx = i;
200+
}
201+
}
202+
return idx;
203+
}
204+
205+
private void dfs(int i, int j, boolean[][] vis) {
206+
vis[i][j] = true;
207+
int idx = areas.size() - 1;
208+
areas.get(idx).add(i * n + j);
209+
for (int k = 0; k < 4; ++k) {
210+
int x = i + DIRS[k], y = j + DIRS[k + 1];
211+
if (x >= 0 && x < m && y >= 0 && y < n) {
212+
if (isInfected[x][y] == 1 && !vis[x][y]) {
213+
dfs(x, y, vis);
214+
} else if (isInfected[x][y] == 0) {
215+
c.set(idx, c.get(idx) + 1);
216+
boundaries.get(idx).add(x * n + y);
217+
}
218+
}
219+
}
220+
}
221+
}
222+
```
85223

224+
### **Go**
225+
226+
```go
227+
func containVirus(isInfected [][]int) int {
228+
m, n := len(isInfected), len(isInfected[0])
229+
ans := 0
230+
dirs := []int{-1, 0, 1, 0, -1}
231+
max := func(boundaries []map[int]bool) int {
232+
idx := 0
233+
mx := len(boundaries[0])
234+
for i, v := range boundaries {
235+
t := len(v)
236+
if mx < t {
237+
mx = t
238+
idx = i
239+
}
240+
}
241+
return idx
242+
}
243+
244+
for {
245+
vis := make([][]bool, m)
246+
for i := range vis {
247+
vis[i] = make([]bool, n)
248+
}
249+
areas := []map[int]bool{}
250+
boundaries := []map[int]bool{}
251+
c := []int{}
252+
253+
var dfs func(i, j int)
254+
dfs = func(i, j int) {
255+
vis[i][j] = true
256+
idx := len(areas) - 1
257+
areas[idx][i*n+j] = true
258+
for k := 0; k < 4; k++ {
259+
x, y := i+dirs[k], j+dirs[k+1]
260+
if x >= 0 && x < m && y >= 0 && y < n {
261+
if isInfected[x][y] == 1 && !vis[x][y] {
262+
dfs(x, y)
263+
} else if isInfected[x][y] == 0 {
264+
c[idx]++
265+
boundaries[idx][x*n+y] = true
266+
}
267+
}
268+
}
269+
}
270+
271+
for i, row := range isInfected {
272+
for j, v := range row {
273+
if v == 1 && !vis[i][j] {
274+
areas = append(areas, map[int]bool{})
275+
boundaries = append(boundaries, map[int]bool{})
276+
c = append(c, 0)
277+
dfs(i, j)
278+
}
279+
}
280+
}
281+
if len(areas) == 0 {
282+
break
283+
}
284+
idx := max(boundaries)
285+
ans += c[idx]
286+
for t, area := range areas {
287+
if t == idx {
288+
for v := range area {
289+
i, j := v/n, v%n
290+
isInfected[i][j] = -1
291+
}
292+
} else {
293+
for v := range area {
294+
i, j := v/n, v%n
295+
for k := 0; k < 4; k++ {
296+
x, y := i+dirs[k], j+dirs[k+1]
297+
if x >= 0 && x < m && y >= 0 && y < n && isInfected[x][y] == 0 {
298+
isInfected[x][y] = 1
299+
}
300+
}
301+
}
302+
}
303+
}
304+
305+
}
306+
return ans
307+
}
86308
```
87309

88310
### **...**

0 commit comments

Comments
 (0)