尽量减少恶意软件的传播
难度:
标签:
题目描述
代码结果
运行时间: 84 ms, 内存: 19.4 MB
/*
* 思路:
* 1. 使用流的API来计算每个节点受到感染的情况。
* 2. 对于每个初始感染节点,将其移除并计算整个网络的感染节点数。
* 3. 选择移除后感染节点数最少的节点作为结果,若有多个,选择索引最小的节点。
*/
import java.util.*;
import java.util.stream.*;
public class MinimizeMalwareSpreadStream {
public int minMalwareSpread(int[][] graph, int[] initial) {
int n = graph.length;
Map<Integer, Integer> infectedBy = IntStream.range(0, n).boxed().collect(Collectors.toMap(i -> i, i -> -1));
Arrays.stream(initial).forEach(node -> {
if (infectedBy.get(node) == -1) {
boolean[] visited = new boolean[n];
dfs(graph, node, node, visited, infectedBy);
}
});
int[] count = new int[n];
infectedBy.values().stream().filter(v -> v != -1).forEach(v -> count[v]++);
return Arrays.stream(initial)
.boxed()
.min(Comparator.comparingInt((Integer node) -> count[node]).thenComparingInt(node -> node))
.orElse(-1);
}
private void dfs(int[][] graph, int start, int node, boolean[] visited, Map<Integer, Integer> infectedBy) {
if (visited[node]) return;
visited[node] = true;
infectedBy.put(node, start);
IntStream.range(0, graph.length)
.filter(i -> graph[node][i] == 1 && !visited[i])
.forEach(i -> dfs(graph, start, i, visited, infectedBy));
}
}
解释
方法:
该题解使用了并查集来解决问题。首先根据图构建并查集,将所有连通的节点合并到同一个集合中。然后遍历初始感染节点列表initial,统计每个集合的感染节点数量。如果某个集合只有一个感染节点,就计算删除该节点后能减少感染的节点数,同时更新能减少最多感染节点数的节点索引。最后返回能减少最多感染节点数且索引最小的节点。
时间复杂度:
O(n^2 + m)
空间复杂度:
O(n + m)
代码细节讲解
🦆
在并查集中,如何处理可能存在的多个连通分量,特别是当它们被不同数量的初始感染节点连接时?
▷🦆
并查集中合并操作的具体实现(Union 方法)是否考虑了按秩合并,以优化性能?
▷🦆
题解中提到的`统计每个集合的感染节点数量`的方法是否能准确区分不同集合中的感染节点,即如何确保计数的准确性?
▷🦆
您提到如果一个集合中只有一个感染节点,删除它将减少该集合的感染节点数。那么如果一个集合中有多个感染节点,删除任何一个是否会影响其它节点的感染状态?
▷