2039. 网络空闲的时刻

网络空闲时刻 — LeetCode 2039 题解与详解

题目描述

给定一个包含 n 个服务器的计算机网络,服务器编号为 0n-1
同时给你一个二维整数数组 edges,其中 edges[i] = [u_i, v_i] 表示服务器 u_i 和服务器 v_i 之间有一条双向的信息线路,信息在线路上传输速度是固定的:1秒可以传输任意多条信息。
还有一个长度为 n 的整数数组 patience,表示每个服务器的重发周期。

题目保证所有服务器都是连通的,也就是说,从任意服务器出发,都可以通过信息线路直达或间接到达任何其他服务器。

  • 服务器编号为 0 的服务器是主服务器,其余都是数据服务器。
  • 在0秒时,所有数据服务器会向主服务器发送消息。
  • 主服务器接收到信息后,会立即处理并沿消息原路径反方向返回回复。
  • 若数据服务器在收到回复之前,间隔时间达到了自己的重发周期 patience[i],会再次发送信息,持续重发,直到收到回复。
  • 当所有信息都传输完毕,且没有新的消息传输时,网络进入空闲状态。

要求返回网络变为空闲状态的最早秒数。


题目要点和难点

  • 图的最短路径问题:所有消息都沿最短路径发送,因为信息传输时间是1秒/条边,无权图最短路径可用 BFS 求出。
  • 重发机制:每个数据服务器会周期性重发信息,直到收到回复,重发的时间点取决于 patience[i]
  • 计算最终空闲时间:需要计算每个服务器最后一次重发信息对应的回复到达时间,取最大值加1秒即为空闲时间。

解题思路

1. 计算最短路径

从主服务器(0号)出发,利用 BFS 计算每个服务器到主服务器的最短距离 dist[i]
该距离即为消息单程传输时间。

2. 计算每个服务器最后收到回复的时间

  • 消息往返时间为 2 * dist[i] 秒。
  • 如果往返时间小于等于重发周期 patience[i],说明服务器只发送一次消息,回复时间即为 2 * dist[i]
  • 否则服务器会重发多次,重发的时间点为 0, patience[i], 2 * patience[i], …,直到收到回复。
  • 最后一次重发消息的发送时间 last_send 可以通过公式计算:
last_send = ((2 * dist[i] - 1) // patience[i]) * patience[i]

这里的 (2 * dist[i] - 1) 是为了向下取整最后一次重发时间。

  • 最后回复时间为 last_send + 2 * dist[i]

3. 计算全网空闲时间

对所有数据服务器计算最后回复时间的最大值,记为 max_reply,网络空闲时间即为:

max_reply + 1

代码实现

from collections import deque, defaultdict
from typing import List

class Solution:
    def networkBecomesIdle(self, edges: List[List[int]], patience: List[int]) -> int:
        n = len(patience)
        graph = defaultdict(list)
        
        # 构建无向图邻接表
        for u, v in edges:
            graph[u].append(v)
            graph[v].append(u)
        
        dist = [-1] * n
        dist[0] = 0
        queue = deque([0])
        
        # BFS求各节点距离主服务器0的最短路径距离
        while queue:
            node = queue.popleft()
            for nei in graph[node]:
                if dist[nei] == -1:
                    dist[nei] = dist[node] + 1
                    queue.append(nei)
        
        ans = 0
        # 计算每个数据服务器最后回复时间,取最大值
        for i in range(1, n):
            time = 2 * dist[i]  # 往返时间
            if time <= patience[i]:
                last_reply = time
            else:
                last_send = ((time - 1) // patience[i]) * patience[i]
                last_reply = last_send + time
            ans = max(ans, last_reply)
        
        return ans + 1

时间复杂度与空间复杂度分析

  • 时间复杂度
    BFS遍历整个图需要 O(n + m),其中 n 是服务器数量,m 是线路数量。
    计算回复时间也是遍历每个服务器,O(n)
    总体时间复杂度:O(n + m)
  • 空间复杂度
    存储邻接表需要 O(n + m)
    存储距离数组需要 O(n)
    总体空间复杂度:O(n + m)

示例解析

示例 1

edges = [[0,1],[1,2]], patience = [0,2,1]
  • 服务器1到主服务器0的距离为1,往返时间为2秒。
    patience[1] = 22 <= 2,服务器1只发1次信息,回复时间为2秒。
  • 服务器2到主服务器0的距离为2,往返时间为4秒。
    patience[2] = 14 > 1,服务器2会多次重发。
    计算最后一次重发发送时间:
last_send = ((4 - 1) // 1) * 1 = 3

最后回复时间为 3 + 4 = 7 秒。

  • 最大回复时间是7秒,空闲时间为 7 + 1 = 8 秒。

示例 2

edges = [[0,1],[0,2],[1,2]], patience = [0,10,10]
  • 服务器1和2的距离都是1,往返时间为2秒。
    patience[1] = patience[2] = 10,都大于往返时间2秒,故都只发送一次消息。
  • 回复时间都是2秒,最大回复时间为2秒,空闲时间为 2 + 1 = 3 秒。

总结

这道题通过 BFS 计算无权图的最短路径,再结合周期性重发策略,巧妙地用数学公式计算出每个服务器最后的回复时间,最后取最大值确定网络空闲时间。

题目考察了图的遍历算法、路径计算和周期性事件模拟的结合,非常经典且实用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值