Skip to content

Commit 56fcc04

Browse files
my solution for 1514
1 parent f2dc388 commit 56fcc04

File tree

1 file changed

+84
-2
lines changed

1 file changed

+84
-2
lines changed

problems/1514/jeremymanning.md

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,93 @@
11
# [Problem 1514: Path with Maximum Probability](https://leetcode.com/problems/path-with-maximum-probability/description/?envType=daily-question)
22

33
## Initial thoughts (stream-of-consciousness)
4+
- First we need a way to represent the graph more conveniently. I'm thinking we should have a hash table whose keys are nodes and whose values are lists of connected nodes + probabilities. E.g., for the first given example, `graph[0] = [(2, 0.2), (1, 0.5)]`, etc. We can build up this hash table with a single pass through the edge list + success probability list:
5+
```python
6+
graph = {}
7+
for edge, prob in zip(edges, succProb):
8+
if edge[0] in graph:
9+
graph[edge[0]].append((edge[1], prob))
10+
else:
11+
graph[edge[0]] = [(edge[1], prob)]
12+
13+
if edge[1] in graph:
14+
graph[edge[1]].append((edge[0], prob))
15+
else:
16+
graph[edge[1]] = [(edge[0], prob)]
17+
```
18+
- Now I think we can build up paths using BFS or DFS starting from `start_node`:
19+
- If we hit a loop, stop and delete that path from the queue/stack
20+
- If we reach `end_node`:
21+
- Go back and compute the probability of this path
22+
- If it's higher than the probability of the current best path (initialized to `0`), replace the best probability
23+
- Then delete the path from the queue/stack
24+
- Potential pitfalls:
25+
- We might run out of memory if we build up the paths one node at a time.
26+
- Ideally we could instead just build up something like probability of the path so far + last node reached. But then I'm not sure we'll be able to detect loops...
27+
- The probabilities could get very small, leading to rounding errors. We could instead track *log* probabilities (summing as we go) and then exponentiate at the end.
28+
- Instead of BFS/DFS, maybe we want to use a heap to keep the paths sorted by max probability.
429

530
## Refining the problem, round 2 thoughts
31+
We could use the built-in `heapq` to do this (according to the documentation `heapq` is a max heap, but we can just multiply the probabilities by -1 so that the most probable paths appear at the "top" of the heap):
32+
- First push the start of the path (`(-1.0, start_node)`) onto the heap
33+
- Keep track of `n` probabilities (of reaching each node). Initialize to 0.0, except the start node (initialize to 1.0).
34+
- While the heap is not empty:
35+
- Pop the most probable path `(prob, last_node)`
36+
- If we're at the end node, return `prob`
37+
- Otherwise:
38+
- For each neighbor `x` of `last_node` (connected with probability `new_prob`):
39+
- Probability of path ending at `x` is `-prob * new_prob`
40+
- If `-prob * new_prob` is greater than `probabilities[x]`:
41+
- Update `probabilities[x]` -- this ensures we only push more probable paths than we've already found onto the heap. This also avoids loops, since visiting an already-visited node will necessarily result in a lower probability path to that node.
42+
- Push `(prob * new_prob, x)` on the heap
43+
- If the heap empties before we found the end, just return 0.0.
644

745
## Attempted solution(s)
846
```python
9-
class Solution: # paste your code here!
10-
...
47+
import heapq
48+
49+
class Solution:
50+
def maxProbability(self, n, edges, succProb, start, end):
51+
# build the graph
52+
graph = {}
53+
for x in range(n):
54+
graph[x] = []
55+
for edge, prob in zip(edges, succProb):
56+
graph[edge[0]].append((edge[1], prob))
57+
graph[edge[1]].append((edge[0], prob))
58+
59+
# max heap
60+
heap = [(-1.0, start)]
61+
probabilities = [0.0] * n
62+
probabilities[start] = 1.0
63+
64+
while heap:
65+
p, node = heapq.heappop(heap)
66+
if node == end:
67+
return -p
68+
69+
for x, xp in graph[node]:
70+
new_prob = p * xp # remember: this is negative
71+
if -new_prob > probabilities[x]:
72+
probabilities[x] = -new_prob
73+
heapq.heappush(heap, (new_prob, x))
74+
75+
# end not found :(
76+
return 0.0
77+
```
78+
- Given test cases pass
79+
- Another example:
80+
```python
81+
n = 7
82+
edges = [[0,1],[1,2],[2,3],[3,4],[4,5],[5,6]]
83+
succProb = [0.01, 0.01, 0.01, 0.01, 0.01, 0.1]
84+
start_node = 0
85+
end_node = 6
1186
```
87+
- passes!
88+
- Ok, submitting!
89+
90+
![Screenshot 2024-08-27 at 12 07 09 AM](https://github.com/user-attachments/assets/3d64e697-53a5-4cbf-a3b4-d397ea27a0f5)
91+
92+
Solved!
93+

0 commit comments

Comments
 (0)