网络空闲时刻 — LeetCode 2039 题解与详解
题目描述
给定一个包含 n
个服务器的计算机网络,服务器编号为 0
到 n-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] = 2
,2 <= 2
,服务器1只发1次信息,回复时间为2秒。 - 服务器2到主服务器0的距离为2,往返时间为4秒。
patience[2] = 1
,4 > 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 计算无权图的最短路径,再结合周期性重发策略,巧妙地用数学公式计算出每个服务器最后的回复时间,最后取最大值确定网络空闲时间。
题目考察了图的遍历算法、路径计算和周期性事件模拟的结合,非常经典且实用。