【LeetCode每日一题】924. 尽量减少恶意软件的传播(并查集)

文章目录


924. 尽量减少恶意软件的传播

思路:并查集
  1. 构建并查集:首先,代码创建了一个 UnionFind 类来维护节点之间的连通关系。它使用了并查集的数据结构,其中 p 数组存储每个节点的父节点,而 size 数组存储每个节点所在集合的大小。
  2. 遍历图并建立连接关系:接下来,代码遍历了给定的图 graph,并对图中存在连接的节点调用 union 方法,将它们所在的集合合并起来。
  3. 统计感染节点数:然后,代码统计了每个初始感染节点所在集合的感染节点数量,并更新了最小节点的值。
  4. 寻找优化的方案:接着,代码再次遍历了初始感染节点数组 initial,对每个节点进行如下操作:
    • 找到该节点所在集合的根节点。
    • 如果该集合中只有一个初始感染节点,那么比较该集合的大小和最大感染节点数,更新答案为当前节点和最大感染节点数。
  5. 返回结果:最后,代码返回了答案,如果没有找到优化的方案,则返回最小节点。
代码:
java 复制代码
class Solution {
    public int minMalwareSpread(int[][] graph, int[] initial) {
        int n = graph.length;
        UnionFind uf = new UnionFind(n);//用并查集维护节点的连通关系
        for (int i = 0; i < n; i++) {
            for (int j = i+1; j < n; j++) {
                if (graph[i][j] == 1) {//如果存在连接
                    uf.union(i, j);//将节点i和节点j所在的集合合并
                }
            }
        }
        int ans = n;
        int min = n;//最小结点
        int max = 0;//最大感染数
        int[] count = new int[n];
        for (int x : initial) {
            count[uf.find(x)]++;//统计每个初始感染节点所在集合的感染节点数量
            min = Math.min(min, x);//更新最小节点
        }
        for (int x : initial) {
            int root = uf.find(x);
            if (count[root] == 1) {
                int size = uf.size(root);
                if (size > max || (size == max && x < ans)) {
                    // 如果当前集合的大小大于最大感染节点数,或者当前集合的大小等于最大感染节点数但节点值较小
                    ans = x;//更新答案为当前节点
                    max = size;//更新最大感染节点数
                }
            }
        }
        return ans == n ? min : ans;//ans==n说明没找到优化的方案,直接返回最小的结点。
    }
}
class UnionFind {
    //维护节点之间的连通关系
    private final int[] p;//存储父结点
    private final int[] size;//存储每个结点所在集合的大小

    public UnionFind(int n) {
        p = new int[n];
        size = new int[n];
        for (int i = 0; i < n; i++) {
            p[i] = i;//把每个父结点设置为自己
            size[i] = 1;//每个集合的初始大小为1
        }
    }

    public int find(int x) {
        //查找结点所在集合的根节点
        if (p[x] != x) {
            //如果父结点不是自己
            p[x] = find(p[x]);
        }
        return p[x];
    }

    public boolean union(int a, int b) { // 将两个节点所在的集合合并
        int pa = find(a);
        int pb = find(b);
        if (pa == pb) {
            //根节点相同,说明两个结点已经是在一个集合中了。
            return false;
        }
        if (size[pa] > size[pb]) {
            p[pb] = pa;//将集合b连接到集合a上
            size[pa] += size[pb];//更新集合a的大小
        }else {
            p[pa] = pb;
            size[pb] += size[pa];
        }
        return true;
    }

    public int size(int root) {
         获取指定根节点所在集合的大小
        return size[root];
    }
}

点击移步博客主页,欢迎光临~

相关推荐
炽烈小老头3 分钟前
【每天学习一点算法 2026/05/20】省份数量
学习·算法
乐迪信息4 分钟前
乐迪信息:港口夜间船舶巡查难,AI摄像机法全天候监测
人工智能·物联网·算法·计算机视觉·目标跟踪
sali-tec5 分钟前
C# 基于OpenCv的视觉工作流-章74-线-线距离
图像处理·人工智能·opencv·算法·计算机视觉
YL200404268 分钟前
054实现Trie(前缀树)
数据结构·leetcode
故事和你919 分钟前
洛谷-【图论2-3】最小生成树1
开发语言·数据结构·c++·算法·动态规划·图论
故事和你9111 分钟前
洛谷-【图论2-3】最小生成树2
开发语言·数据结构·c++·算法·动态规划·图论
guygg8812 分钟前
贝叶斯非局部均值降噪算法C语言实现
c语言·算法·均值算法
量子炒饭大师13 分钟前
【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?
c++·算法·重构·优化算法·双指针·滑动窗口
玖釉-15 分钟前
C++ 中的 buckets 详解:从哈希桶到 unordered_map 底层原理
算法·哈希算法·散列表
计算机安禾15 分钟前
【c++面向对象编程】第35篇:构造函数与异常:如何避免资源泄露?
开发语言·javascript·c++·算法·性能优化