Skip to content

Commit 95d511b

Browse files
committed
Added Dijkstra with heaps.
1 parent 8a87b51 commit 95d511b

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

leetcode/medium/743_network_delay_time.md

+59-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# 743. Network Delay Time
22

3-
## Dijkstra's Algorithm Solution
4-
- Run-time: O(N^2)
5-
- Space: O(N)
6-
- N = Number of Nodes
3+
## Simple Dijkstra's Algorithm Solution
4+
- Run-time: O(V^2)
5+
- Space: O(V)
6+
- V = Number of Vertices
77

88
This version of Dijkstra is fairly straightforward.
99
For each iteration from 1 to N.
@@ -45,5 +45,60 @@ class Solution:
4545

4646
## Dijkstra's Algorithm Solution with Heaps
4747

48+
- Run-time: O((V + E)logV)
49+
- Space: O(V)
50+
- V = Vertices
51+
- E = Edges
52+
53+
As explained in question #1135, there is no adaptable heap implementation in Python 3.7.
54+
Instead, we will be using a lazy deletion method, similar to question #1135.
55+
56+
The only difference between Prim vs. Dijkstra is adding/updating with the previous weights in the heap nodes.
57+
In Prim's we only care about the next weight.
58+
In Dijkstra, since we want the shortest paths, we need to reevaluate the weights by checking if we can produce an even smaller weight.
59+
Therefore, we need to compare between the shortest path to neighboring vertex vs. the current vertex's shortest path + current weight to neighboring vertex.
60+
4861
```
62+
from collections import defaultdict
63+
64+
class Solution:
65+
def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int:
66+
67+
def create_adj_list():
68+
adj_list = defaultdict(list)
69+
for source, target, time in times:
70+
adj_list[source].append([target, time])
71+
return adj_list
72+
73+
def add_target(target, time):
74+
new_node = [time, target, False]
75+
target_to_heap_node[target] = new_node
76+
heapq.heappush(min_heap, new_node)
77+
78+
adj_list = create_adj_list()
79+
start_node = [0, K, False] # time, source, remove
80+
target_to_heap_node = dict({K: start_node}) # key=target, val=time
81+
min_heap = list([start_node])
82+
times = defaultdict(lambda: float('inf')) # key=source, val=time
83+
times[K] = 0
84+
visited = set()
85+
while min_heap:
86+
time, source, remove = heapq.heappop(min_heap)
87+
if remove: # lazy delete
88+
continue
89+
visited.add(source)
90+
for next_target, t in adj_list[source]:
91+
if next_target in visited:
92+
continue
93+
next_time = t + time
94+
if next_target in target_to_heap_node:
95+
node = target_to_heap_node[next_target]
96+
if next_time < node[0]:
97+
node[2] = True # lazy delete
98+
add_target(next_target, next_time)
99+
else:
100+
add_target(next_target, next_time)
101+
target_to_heap_node.pop(source)
102+
times[source] = min(times[source], time)
103+
return max(times.values()) if len(times) == N else -1
49104
```

0 commit comments

Comments
 (0)