网络延迟时间
有 N 个网络节点,标记为 1 到 N。
给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。
现在,我们向当前的节点 K 发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。
注意:
N 的范围在 [1, 100] 之间。
K 的范围在 [1, N] 之间。
times 的长度在 [1, 6000] 之间。
所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 0 <= w <= 100。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/network-delay-time
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
一开始的想法:
public int networkDelayTime(int[][] times, int N, int K) {
Set<Integer> set = new HashSet<>(N);
int[] dist = new int[N + 1];
for (int i = 0; i < dist.length; i++) {
dist[i] = Integer.MAX_VALUE;
}
dist[K] = 0;
for (int i = 0; i < N; i++) {
set.add(K);
for (int j = 0; j < times.length; j++) {
if (times[j][0] == K && !set.contains(times[j][1]))
if (times[j][2] + dist[K] < dist[times[j][1]])
dist[times[j][1]] = times[j][2] + dist[K];
}
for (int j = 1; j < dist.length; j++) {
if (set.contains(j))
continue;
if (dist[j] <= dist[0]) {
dist[0] = dist[j];
K = j;
}
}
dist[0] = Integer.MAX_VALUE;
}
dist[0] = 0;
for (int i = 1; i < dist.length; i++) {
if (dist[i] == Integer.MAX_VALUE)
return -1;
else if (dist[i] > dist[0])
dist[0] = dist[i];
}
return dist[0];
}
参考评论:
/**
* Floyd-Warshall 算法
* 丁大勺
*/
public int networkDelayTime(int[][] times, int N, int K) {
/*
本质上是求单点到所有其他点的最短距离,最后求最短距离中的最大值。
使用Floyd-Warshall 算法求解。
*/
K--; //输入中节点编号是基1,故减1
int[] dis = new int[N]; //存储K到每个点的最短距离
for (int i = 0; i < N; i++) {
dis[i] = Integer.MAX_VALUE;
}
dis[K] = 0;
for (int i = 0; i < N; i++) {
for (int[] edge : times) {
//输入中节点编号是基1,故减1
int u = edge[0] - 1, v = edge[1] - 1, w = edge[2];
if (dis[u] != Integer.MAX_VALUE && dis[v] > dis[u] + w)
dis[v] = dis[u] + w;
}
}
//求最短距离中的最大值
int res = 0;
for (int i = 0; i < N; i++) {
res = Math.max(res, dis[i]);
}
return res == Integer.MAX_VALUE ? -1 : res;
}
结果:
public int networkDelayTime1(int[][] times, int N, int K) {
int[] dist = new int[N + 1];
for (int i = 0; i < dist.length; i++) {
dist[i] = Integer.MAX_VALUE;
}
dist[K] = 0;
for (int i = 0; i < N; i++) {
for (int[] edge : times) {
int u = edge[0], v = edge[1], w = edge[2];
if (dist[u] != Integer.MAX_VALUE && dist[v] > dist[u] + w)
dist[v] = dist[u] + w;
}
}
int res = 0;//dist[0] = 0;
for (int i = 1; i <= N; i++) {
if ((res = Math.max(res, dist[i])) == Integer.MAX_VALUE)
return -1;
}
return res;
}
总结:发现使用数组来存储比使用单个变量来存储更加消耗内存和时间,对Floyd - Warshall算法和Dijkstra算法理解的不够透彻,思维不够程序化,对计算机来说,有时候直接遍历是最快的。
吐槽一下leetcode,明明同样的代码,第一次提交运行38ms,第二次就67ms了,有点迷...