|
| 1 | +# 743. 网络延迟时间 - 力扣题解最佳实践 |
| 2 | +力扣链接:[743. 网络延迟时间](https://leetcode.cn/problems/network-delay-time), 难度: **中等**。 |
| 3 | + |
| 4 | +## 力扣“743. 网络延迟时间”问题描述 |
| 5 | +有 `n` 个网络节点,标记为 `1` 到 `n`。 |
| 6 | + |
| 7 | +给你一个列表 `times`,表示信号经过 **有向** 边的传递时间。 `times[i] = (ui, vi, wi)`,其中 `ui` 是源节点,`vi` 是目标节点, `wi` 是一个信号从源节点传递到目标节点的时间。 |
| 8 | + |
| 9 | +现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 `-1` 。 |
| 10 | + |
| 11 | +### [示例 1] |
| 12 | + |
| 13 | + |
| 14 | +**输入**: `times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2` |
| 15 | + |
| 16 | +**输出**: `2` |
| 17 | + |
| 18 | +### [示例 2] |
| 19 | +**输入**: `times = [[1,2,1]], n = 2, k = 1` |
| 20 | + |
| 21 | +**输出**: `1` |
| 22 | + |
| 23 | +### [示例 3] |
| 24 | +**输入**: `times = [[1,2,1]], n = 2, k = 2` |
| 25 | + |
| 26 | +**输出**: `-1` |
| 27 | + |
| 28 | +### [约束] |
| 29 | +- `1 <= k <= n <= 100` |
| 30 | +- `1 <= times.length <= 6000` |
| 31 | +- `times[i].length == 3` |
| 32 | +- `1 <= ui, vi <= n` |
| 33 | +- `ui != vi` |
| 34 | +- `0 <= wi <= 100` |
| 35 | +- 所有 `(ui, vi)` 对都 **互不相同**(即,不含重复边) |
| 36 | + |
| 37 | +### [提示] |
| 38 | +<details> |
| 39 | + <summary>提示 1</summary> |
| 40 | + We visit each node at some time, and if that time is better than the fastest time we've reached this node, we travel along outgoing edges in sorted order. Alternatively, we could use Dijkstra's algorithm. |
| 41 | +</details> |
| 42 | + |
| 43 | +## 思路 |
| 44 | +本题可用 **Bellman-Ford算法** 或 **Dijkstra算法** 解决。 |
| 45 | + |
| 46 | +`Bellman-Ford`算法代码量少,还能处理`边`权值为**负数**的情况,但较慢。 |
| 47 | + |
| 48 | +`Dijkstra算法`因为始终走最短路径,所以执行**效率高**!但代码量大,无法处理`边`权值为**负数**的情况。 |
| 49 | + |
| 50 | +**Dijkstra算法**的详细说明,请参考 [1514. 概率最大的路径](../1001-2000/1514-path-with-maximum-probability.md)。 |
| 51 | + |
| 52 | +## 复杂度 |
| 53 | +**V**: 顶点数量,**E**: 边的数量。 |
| 54 | + |
| 55 | +### Bellman-Ford 算法 |
| 56 | +* 时间: `O(V * E)`. |
| 57 | +* 空间: `O(V)`. |
| 58 | + |
| 59 | +### Dijkstra 算法(采用`堆排序`) |
| 60 | +* 时间: `O(E * log(E))`. |
| 61 | +* 空间: `O(V + E)`. |
| 62 | + |
| 63 | +## Python |
| 64 | +### Standard Bellman-Ford algorithm |
| 65 | +```python |
| 66 | +class Solution: |
| 67 | + def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int: |
| 68 | + min_times = [float('inf')] * (n + 1) |
| 69 | + min_times[start] = 0 |
| 70 | + |
| 71 | + for _ in range(n - 1): |
| 72 | + for source_node, target_node, time in edges: # process edges directly |
| 73 | + if min_times[source_node] == float('inf'): |
| 74 | + continue |
| 75 | + |
| 76 | + target_time = time + min_times[source_node] |
| 77 | + |
| 78 | + if target_time < min_times[target_node]: |
| 79 | + min_times[target_node] = target_time |
| 80 | + |
| 81 | + result = max(min_times[1:]) |
| 82 | + |
| 83 | + if result == float('inf'): |
| 84 | + return -1 |
| 85 | + |
| 86 | + return result |
| 87 | +``` |
| 88 | + |
| 89 | +### Algorithm similar to Bellman-Ford algorithm |
| 90 | +```python |
| 91 | +class Solution: |
| 92 | + def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int: |
| 93 | + min_times = [float('inf')] * (n + 1) |
| 94 | + min_times[start] = 0 |
| 95 | + node_to_pairs = defaultdict(set) |
| 96 | + |
| 97 | + for source, target, time in edges: # process nodes first, then their edges |
| 98 | + node_to_pairs[source].add((target, time)) |
| 99 | + |
| 100 | + for _ in range(n - 1): |
| 101 | + for node, min_time in enumerate(min_times): # process nodes first |
| 102 | + if min_time == float('inf'): |
| 103 | + continue |
| 104 | + |
| 105 | + for target_node, time in node_to_pairs[node]: # process edges of the node |
| 106 | + target_time = time + min_time |
| 107 | + |
| 108 | + if target_time < min_times[target_node]: |
| 109 | + min_times[target_node] = target_time |
| 110 | + |
| 111 | + result = max(min_times[1:]) |
| 112 | + |
| 113 | + if result == float('inf'): |
| 114 | + return -1 |
| 115 | + |
| 116 | + return result |
| 117 | +``` |
| 118 | + |
| 119 | +### Dijkstra's algorithm using `heap sort` (without `visited`) |
| 120 | +```python |
| 121 | +import heapq |
| 122 | + |
| 123 | +class Solution: |
| 124 | + def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int: |
| 125 | + min_times = [float('inf')] * (n + 1) |
| 126 | + min_times[start_node] = 0 |
| 127 | + node_to_pairs = defaultdict(set) |
| 128 | + |
| 129 | + for source, target, time in edges: |
| 130 | + node_to_pairs[source].add((target, time)) |
| 131 | + |
| 132 | + priority_queue = [(0, start_node)] |
| 133 | + |
| 134 | + while priority_queue: |
| 135 | + current_time, current_node = heapq.heappop(priority_queue) |
| 136 | + |
| 137 | + for target_node, time in node_to_pairs[current_node]: |
| 138 | + target_time = time + current_time |
| 139 | + |
| 140 | + if target_time < min_times[target_node]: |
| 141 | + min_times[target_node] = target_time |
| 142 | + heapq.heappush(priority_queue, (target_time, target_node)) |
| 143 | + |
| 144 | + result = max(min_times[1:]) |
| 145 | + |
| 146 | + if result == float('inf'): |
| 147 | + return -1 |
| 148 | + |
| 149 | + return result |
| 150 | +``` |
| 151 | + |
| 152 | +### Dijkstra's algorithm using `heap sort` (with `visited`) |
| 153 | +```python |
| 154 | +import heapq |
| 155 | + |
| 156 | +class Solution: |
| 157 | + def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int: |
| 158 | + min_times = [float('inf')] * (n + 1) |
| 159 | + min_times[start_node] = 0 |
| 160 | + node_to_pairs = defaultdict(set) |
| 161 | + visited = [False] * (n + 1) # added 1 |
| 162 | + |
| 163 | + for source, target, time in edges: |
| 164 | + node_to_pairs[source].add((target, time)) |
| 165 | + |
| 166 | + priority_queue = [(0, start_node)] |
| 167 | + |
| 168 | + while priority_queue: |
| 169 | + current_time, current_node = heapq.heappop(priority_queue) |
| 170 | + |
| 171 | + if visited[current_node]: # added 3 |
| 172 | + continue |
| 173 | + |
| 174 | + visited[current_node] = True # added 2 |
| 175 | + |
| 176 | + for target_node, time in node_to_pairs[current_node]: |
| 177 | + if visited[target_node]: # added 4 |
| 178 | + continue |
| 179 | + |
| 180 | + target_time = time + current_time |
| 181 | + |
| 182 | + if target_time < min_times[target_node]: |
| 183 | + min_times[target_node] = target_time |
| 184 | + heapq.heappush(priority_queue, (target_time, target_node)) |
| 185 | + |
| 186 | + result = max(min_times[1:]) |
| 187 | + |
| 188 | + if result == float('inf'): |
| 189 | + return -1 |
| 190 | + |
| 191 | + return result |
| 192 | +``` |
| 193 | + |
| 194 | +## JavaScript |
| 195 | +```javascript |
| 196 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 197 | +``` |
| 198 | + |
| 199 | +## Java |
| 200 | +```java |
| 201 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 202 | +``` |
| 203 | + |
| 204 | +## C++ |
| 205 | +```cpp |
| 206 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 207 | +``` |
| 208 | + |
| 209 | +## C# |
| 210 | +```c# |
| 211 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 212 | +``` |
| 213 | + |
| 214 | +## Go |
| 215 | +```go |
| 216 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 217 | +``` |
| 218 | + |
| 219 | +## Ruby |
| 220 | +```ruby |
| 221 | +# Welcome to create a PR to complete the code of this language, thanks! |
| 222 | +``` |
| 223 | + |
| 224 | +## C, Kotlin, Swift, Rust or other languages |
| 225 | +``` |
| 226 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 227 | +``` |
0 commit comments