Skip to content

Commit

Permalink
feat(1514): Medium
Browse files Browse the repository at this point in the history
You are given an undirected weighted graph of n nodes (0-indexed), represented by an edge list where edges[i] = [a, b] is an undirected edge connecting the nodes a and b with a probability of success of traversing that edge succProb[i].

Given two nodes start and end, find the path with the maximum probability of success to go from start to end and return its success probability.

If there is no path from start to end, return 0. Your answer will be accepted if it differs from the correct answer by at most 1e-5.

Example 1:

Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
Output: 0.25000
Explanation: There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
Example 2:

Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
Output: 0.30000
Example 3:

Input: n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
Output: 0.00000
Explanation: There is no path between 0 and 2.

Constraints:

2 <= n <= 10^4
0 <= start, end < n
start != end
0 <= a, b < n
a != b
0 <= succProb.length == edges.length <= 2*10^4
0 <= succProb[i] <= 1
There is at most one edge between every two nodes.
  • Loading branch information
DziedzicGrzegorz committed Aug 27, 2024
1 parent 0834392 commit b70073f
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
55 changes: 55 additions & 0 deletions internal/Leetcode/1514/1514.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package _1514

import (
"container/heap"
)

func maxProbability(n int, edges [][]int, succProb []float64, start_node int, end_node int) float64 {
// 2 dim array with map
graph := make([]map[int]float64, n)
for i := range graph {
graph[i] = make(map[int]float64)
}
//maxHeap as priority queue
maxHeap := make(PriorityQueue, 0)
//init graph
maxHeap.Push(&Item{value: start_node, priority: 1})

seen := make([]bool, n)

for i := range edges {
u := edges[i][0]
v := edges[i][1]
prob := succProb[i]
//graph = append(graph, map[int]float64{v: prob})
//graph = append(graph, map[int]float64{u: prob})
graph[u][v] = prob
graph[v][u] = prob

}

for maxHeap.Len() > 0 {
item := heap.Pop(&maxHeap).(*Item)
prob := item.priority
u := item.value

if u == end_node {
return prob
}

if seen[u] {
continue

Check warning on line 41 in internal/Leetcode/1514/1514.go

View check run for this annotation

Codecov / codecov/patch

internal/Leetcode/1514/1514.go#L41

Added line #L41 was not covered by tests
}

seen[u] = true

for nextNode, edgeProb := range graph[u] {
if seen[nextNode] {
continue
}
heap.Push(&maxHeap, &Item{value: nextNode, priority: prob * edgeProb})
}
}

return 0.0

Check warning on line 54 in internal/Leetcode/1514/1514.go

View check run for this annotation

Codecov / codecov/patch

internal/Leetcode/1514/1514.go#L54

Added line #L54 was not covered by tests
}
39 changes: 39 additions & 0 deletions internal/Leetcode/1514/1514_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package _1514

import (
"testing"
)

func Test_maxProbability(t *testing.T) {
type args struct {
n int
edges [][]int
succProb []float64
start_node int
end_node int
}
tests := []struct {
name string
args args
want float64
}{
{
name: "test case 1",
args: args{
n: 3,
edges: [][]int{{0, 1}, {1, 2}, {0, 2}},
succProb: []float64{0.5, 0.5, 0.2},
start_node: 0,
end_node: 2,
},
want: 0.25,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := maxProbability(tt.args.n, tt.args.edges, tt.args.succProb, tt.args.start_node, tt.args.end_node); got != tt.want {
t.Errorf("maxProbability() = %v, want %v", got, tt.want)
}
})
}
}
34 changes: 34 additions & 0 deletions internal/Leetcode/1514/PriorityQueue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package _1514

// An Item is something we manage in a priority queue.
type Item struct {
value int
priority float64
}

// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
item := x.(*Item)
*pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
*pq = old[0 : n-1]
return item
}

0 comments on commit b70073f

Please sign in to comment.