• 924. 尽量减少恶意软件的传播 前缀和


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

    给出了一个由 n 个节点组成的网络,用 n × n 个邻接矩阵图 graph 表示。在节点网络中,当 graph[i][j] = 1 时,表示节点 i 能够直接连接到另一个节点 j。 

    一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。

    假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。

    如果从 initial 中移除某一节点能够最小化 M(initial), 返回该节点。如果有多个节点满足条件,就返回索引最小的节点。

    请注意,如果某个节点已从受感染节点的列表 initial 中删除,它以后仍有可能因恶意软件传播而受到感染。

    示例 1:

    输入:graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
    输出:0
    

    示例 2:

    输入:graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]
    输出:0
    

    示例 3:

    输入:graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]
    输出:1
    

    提示:

    • n == graph.length
    • n == graph[i].length
    • 2 <= n <= 300
    • graph[i][j] == 0 或 1.
    • graph[i][j] == graph[j][i]
    • graph[i][i] == 1
    • 1 <= initial.length <= n
    • 0 <= initial[i] <= n - 1
    • initial 中所有整数均不重复

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/minimize-malware-spread
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    做题结果

    成功,题目描述不是特别清晰,其实是无向图,题目简单的用连接两个字概括有点不清楚;另外索引其实指的是图中的索引,initial的索引。删除表示初始感染不包含此元素,并不是真的删除掉该元素,也不是该元素不能被传播。

    方法:前缀和

    想到每个元素之间有相互包含的情况,会比较复杂,不能说全部加起来再减掉一块。那可以采用前缀后缀方法,可以参考这题:剑指 Offer 66. 构建乘积数组

    1. 提前算出后缀,再把它和前缀组合起来,就变成除了当前元素之外其他元素的结果长度。

    2. 索引尽可能小。给initial 排个序(前面dfs过程实际每加一层都循环一次n,相当于 n 方复杂度,这里 nlogn 无伤大雅),后面只有小于前面的情况才替换即可,这里可以少一点if判断

    1. class Solution {
    2. Set []spreads;
    3. public int minMalwareSpread(int[][] graph, int[] initial) {
    4. int n = graph.length;
    5. //循环graph n方,排个序肯定比它小
    6. Arrays.sort(initial);
    7. int m = initial.length;
    8. //每个点能传播到多少点
    9. spreads = new HashSet[m];
    10. for(int i = 0; i < m; i++){
    11. spreads[i] = new HashSet<>();
    12. dfs(spreads[i],initial[i],graph);
    13. }
    14. //哈希后缀,代表传播了多少人 [i,m-1]
    15. Set[] lasts = new HashSet[m+1];
    16. lasts[m] = new HashSet<>();
    17. for(int i = m-1; i >= 0; i--){
    18. Set tmp = new HashSet<>(lasts[i+1]);
    19. tmp.addAll(spreads[i]);
    20. lasts[i] = tmp;
    21. }
    22. int ans = initial[0];
    23. int spread = Integer.MAX_VALUE;
    24. //哈希前缀,代表传播了多少人
    25. Set tmp = new HashSet<>();
    26. for(int i = 0; i < m; i++){
    27. //前+后=不包括自己的
    28. Set curr = new HashSet<>(tmp);
    29. curr.addAll(lasts[i+1]);
    30. //成功减少恶意软件传播,替换答案
    31. // (索引问题,由于排序不存在后面比前面小的情况,判断变简单)
    32. if(curr.size()
    33. spread = curr.size();
    34. ans = initial[i];
    35. }
    36. tmp.addAll(spreads[i]);
    37. }
    38. return ans;
    39. }
    40. private void dfs(Set spread, int index, int[][] graph) {
    41. if(spread.contains(index)) return;
    42. spread.add(index);
    43. for(int i = 0; i < graph[index].length; i++){
    44. if(graph[index][i]==1){
    45. dfs(spread,i,graph);
    46. }
    47. }
    48. }
    49. }

  • 相关阅读:
    2023/9/8 -- C++/QT
    three物体围绕一周呈球形排列
    进一步观察扩散模型中的参数有效调整
    C#多线程学习(二) 如何操纵一个线程
    十进制分钟转时间类型
    抖音小店怎么做自然流量?
    Machine Learning(study notes)
    从零开始—仿牛客网讨论社区项目(一)
    初识Java 18-2 泛型
    ISCSLP 2022 | AccentSpeech—从众包数据中学习口音来构建目标说话人的口音语音合成系统
  • 原文地址:https://blog.csdn.net/yu_duan_hun/article/details/126129984