leetcode
leetcode 851 ~ 900
尽量减少恶意软件的传播 II

尽量减少恶意软件的传播 II

难度:

标签:

题目描述

代码结果

运行时间: 47 ms, 内存: 20.3 MB


/*
 * 思路:
 * 1. 使用DFS(深度优先搜索)来找到每个节点可以感染的所有节点。
 * 2. 计算每个初始感染节点的贡献值,即移除该节点后,减少的感染节点数。
 * 3. 返回贡献值最大的节点,如果有多个,返回索引最小的节点。
 */

import java.util.*;
import java.util.stream.*;

public class Solution {
    public int minMalwareSpread(int[][] graph, int[] initial) {
        int n = graph.length;
        int[] infectedBy = new int[n];
        Arrays.fill(infectedBy, -1);

        for (int node : initial) {
            dfs(graph, node, node, infectedBy, new boolean[n]);
        }

        int[] contribution = new int[n];
        IntStream.range(0, n).filter(i -> infectedBy[i] != -1).forEach(i -> contribution[infectedBy[i]]++);

        return Arrays.stream(initial)
                     .boxed()
                     .min((a, b) -> contribution[a] != contribution[b] ? Integer.compare(contribution[b], contribution[a]) : Integer.compare(a, b))
                     .orElse(-1);
    }

    private void dfs(int[][] graph, int start, int infected, int[] infectedBy, boolean[] visited) {
        if (visited[start]) return;
        visited[start] = true;
        infectedBy[start] = infected;
        for (int i = 0; i < graph.length; i++) {
            if (graph[start][i] == 1 && !visited[i]) {
                dfs(graph, i, infected, infectedBy, visited);
            }
        }
    }
}

解释

方法:

这个题解的思路是通过深度优先搜索(DFS)来探索每个初始感染节点的影响范围,以确定在移除某个初始感染节点后,能够最大程度减少网络中感染的节点数量。首先,使用一个数组 `initial_record` 来标记哪些节点是初始感染节点。对每个初始感染节点进行测试,即假设将其移除,然后使用DFS来计算如果移除该节点后,由该节点直接或间接连接的节点中,有多少节点会被感染。对于每个通过DFS访问的节点,如果它是一个初始感染节点,就立即停止进一步的搜索。这样可以模拟该节点被移除后的情况。最后,选择能够使最终感染节点数最小化的节点,如果有多个节点都能达到最小化效果,则返回索引最小的节点。

时间复杂度:

O(k * (n + m))

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中,为什么在DFS过程中遇到初始感染节点就立即停止搜索?这种处理方式对结果有什么影响?
在题解中,DFS用于估算移除某个初始感染节点后,其他节点受影响的程度。遇到其他初始感染节点时立即停止搜索是因为,如果不停止,我们会错误地计算由其他初始感染节点导致的感染范围作为当前考察节点的影响,这将导致结果不准确。此处理方式确保了我们只计算非初始感染节点的传播影响,从而准确评估在移除特定初始感染节点后,网络中感染的节点数的减少。
🦆
题解中提到了在DFS中进行回溯,标记节点未访问,并将节点标记为感染。这种回溯操作在算法中起到了什么作用?是否存在潜在的错误或逻辑不一致?
题解中的回溯操作似乎存在逻辑不一致。正常的回溯操作应该是在DFS完成后,将节点标记为未访问,以供其他DFS路径再次访问。而在题解中,回溯同时标记节点为感染和未访问,这是矛盾的。标记为感染应该表示节点在场景中是不可避免地被感染的,而标记为未访问则意味着该节点在后续的搜索中可以被重新探索。这种处理可能会导致算法在后续的执行中出现错误,如重复计算或逻辑判断错误。
🦆
题解描述了一个'最终感染节点数最小化'的目标。请问这个目标是如何通过算法实现的?具体的逻辑是什么?
题解通过模拟移除每个初始感染节点并使用DFS计算其影响范围来实现'最终感染节点数最小化'的目标。具体逻辑是:首先记录每个初始感染节点,然后逐个假设移除这些节点。对于每个假设移除的节点,使用DFS计算其直接或间接连接的非初始感染节点的数量。通过比较移除不同节点后的感染节点数量,选择能够使感染节点数最小化的节点。如果多个节点都能达到最小化效果,则返回索引最小的节点。这种方法通过直接计算每个操作的影响,找到最优解。

相关问题