forked from AnasImloul/Leetcode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathContain Virus.js
96 lines (77 loc) · 3.53 KB
/
Contain Virus.js
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
var containVirus = function(isInfected) {
const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]];
let walls = 0;
function findContaminated() {
let visited = {}, infected = [];
let mostViral;
for (let i = 0; i < isInfected.length; i++) {
for (let j = 0; j < isInfected[i].length; j++) {
if (isInfected[i][j] === 1) {
let key = `${i}-${j}`;
if (key in visited) continue;
else infected.push([i, j]);
let zeroes = new Set();
let perimeter = findPerimeter(i, j, visited, zeroes);
// Find the largest potential infection perimeter based on the number of 0's neighboring infected cells
if (!mostViral) mostViral = {i, j, perimeter, zeroes: zeroes.size};
else if (zeroes.size > mostViral.zeroes) mostViral = {i, j, perimeter, zeroes: zeroes.size};
}
}
}
if (mostViral) {
walls += mostViral.perimeter;
// Quarantine the most viral area
quarantine(mostViral.i, mostViral.j);
// Spread the infection throughout the remaining infected areas
let alreadyInfected = {};
for (let [row, col] of infected) {
if (mostViral.i === row && mostViral.j === col) continue;
else infect(row, col, alreadyInfected);
}
return true;
}
return false;
}
while (findContaminated()) continue;
return walls;
function findPerimeter(row, col, visited, zeroes) {
if (row < 0 || col < 0 || row >= isInfected.length || col >= isInfected[0].length) return 0;
let key = `${row}-${col}`;
// If the current cell is visited or quarantined, leave the perimeter unchanged
if (visited[key] || isInfected[row][col] === -1) return 0;
// If the current cell is not infected and not quarantined, increase the perimeter
if (isInfected[row][col] === 0) {
zeroes.add(key);
return 1;
}
visited[key] = true;
let perimeter = 0;
for (let [r, c] of directions) {
perimeter += findPerimeter(row + r, col + c, visited, zeroes);
}
return perimeter;
}
function quarantine(row, col) {
if (row < 0 || col < 0 || row >= isInfected.length || col >= isInfected[0].length) return;
// Only quarantine infected cells and neighboring infected cells
if (isInfected[row][col] === 1) isInfected[row][col] = -1;
else return;
for (let [r, c] of directions) quarantine(row + r, col + c);
}
function infect(row, col, alreadyInfected, neighbor = 0) {
if (row < 0 || col < 0 || row >= isInfected.length || col >= isInfected[0].length) return;
let key = `${row}-${col}`;
// If the current cell is already infected or quarantined
if (alreadyInfected[key] || isInfected[row][col] === -1) return;
// If the current cell is clear but neighbors an infected cell, infect it
if (isInfected[row][col] === 0 && neighbor === 1) {
alreadyInfected[key] = true;
return isInfected[row][col] = 1;
}
else if (isInfected[row][col] === 1 && neighbor === 1) {
alreadyInfected[key] = true;
neighbor = 0;
}
for (let [r, c] of directions) infect(row + r, col + c, alreadyInfected, neighbor + 1);
}
};