网络延迟时间
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
图一:
示例 1:图一
输入:times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
输出:2
示例 2:
输入:times = [[1,2,1]], n = 2, k = 1
输出:1
示例 3:
输入:times = [[1,2,1]], n = 2, k = 2
输出:-1
思路一
function networkDelayTime(times, N, K) {
const graph = Array.from({length: N}, () => []);
const dist = Array(N).fill(Infinity);
dist[K - 1] = 0; // 节点编号从1开始,数组索引从0开始
const pq = []; // 优先级队列,存放待访问的节点
// 构建邻接表
for (const [u, v, w] of times) {
graph[u - 1].push([v - 1, w]);
}
// 初始化优先级队列
pq.push([0, K - 1]); // [distance, node]
while (pq.length > 0) {
pq.sort((a, b) => a[0] - b[0]); // 每次取最小距离的节点
const [d, u] = pq.shift();
if (d > dist[u]) continue; // 如果当前节点已经更新过距离,跳过
for (const [v, w] of graph[u]) {
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pq.push([dist[v], v]);
}
}
}
const maxDist = Math.max(...dist);
return maxDist === Infinity ? -1 : maxDist;
}
讲解
这个问题可以通过最短路径算法来解决,具体来说,可以使用Bellman-Ford算法或者Dijkstra算法的变种。但是,由于图是有向图并且没有负权重边,Dijkstra算法会更高效一些。
- 初始化距离数组:创建一个数组dist,其长度等于节点的数量,用来存储从起始节点K到每个节点的最短距离。将dist[K]设为0,表示从K到自身的距离为0,其他节点的距离初值设为Infinity,表示初始时距离未知。
- 构建邻接表:遍历times数组,将边的信息构建成邻接表,这样可以方便地查找从一个节点出发的所有可能的下一站点及对应的权重。
- 使用Dijkstra算法:从起始节点K开始,使用优先级队列(最小堆)来保存待访问的节点,每次从队列中取出具有最小距离的节点,更新其邻居的距离,如果更新后的距离小于之前的记录,则更新距离,并将该邻居加入到队列中等待处理。
- 检查是否所有节点都可达:最后检查dist数组中是否有节点的距离仍然保持为Infinity,如果有,说明存在节点无法到达,返回-1;否则,返回dist数组中的最大值,这代表了信号到达最远节点所花费的时间。