先簡單回顧一下,今天預計分析的題目:
題目連結:https://leetcode.com/problems/path-with-maximum-probability/
題目敘述
測資的 Input/Output
由於 n 可能到 10000,用二維陣列儲存 edge 的話,效能不佳。因此此處使用 list 的方式紀錄每一點存在的邊。
mapping = [[] for _ in range(n)]
for i in range(len(edges)):
(a, b), prob = edges[i], succProb[i]
mapping[a].append((b, prob))
mapping[b].append((a, prob))
雖然是求最大機率,但由於機率相乘只會越來越小 (因為機率 ≤ 1),正好可以使用 dijkstra 來解此問題。
新的路徑長 ≥ 原始路徑長
。新的權重≥ 原始權重
。使用 dijkstra 演算法,我們需要開一個一維陣列儲存最大機率(最短路徑)。
maxProb = [0] * n
maxProb[start] = 1
100%
,因而設為 1
。1 x 1 = 1
。依據 Dijkstra,每一輪要找出機率最大者進行走訪(路徑長最小者),然而如果每一輪都要掃描一次找出最大值,會嚴重影響效能,導致 TLE,此處我們使用 priority queue 來實作。
pq = [(-1, start)]
while pq:
curProb, cur = heapq.heappop(pq)
curProb = -curProb
if cur == end: break
若還沒走到終點,則以現在的節點出發,若能走出更大的機率,就將該節點與機率放入 queue 中。
for i, prob in mapping[cur]:
newProb = curProb * prob
if newProb > maxProb[i]:
maxProb[i] = newProb
heapq.heappush(pq, (-newProb, i))
最後,回傳走到終點最大機率
return maxProb[end]
完整程式碼如下:
class Solution:
def maxProbability(self, n: int, edges: List[List[int]], succProb: List[float], start: int, end: int) -> float:
mapping = [[] for _ in range(n)]
for i in range(len(edges)):
(a, b), prob = edges[i], succProb[i]
mapping[a].append((b, prob))
mapping[b].append((a, prob))
maxProb = [0] * n
maxProb[start] = 1
pq = [(-1, start)]
while pq:
curProb, cur = heapq.heappop(pq)
curProb = -curProb
if cur == end: break
for i, prob in mapping[cur]:
newProb = curProb * prob
if newProb > maxProb[i]:
maxProb[i] = newProb
heapq.heappush(pq, (-newProb, i))
return maxProb[end]
heapq 參考資料:https://docs.python.org/zh-tw/3/library/heapq.html