#1786

Number of Restricted Paths From First to Last Node

Medium
Dynamic ProgrammingGraph TheoryTopological SortHeap (Priority Queue)Shortest PathGraph TraversalDynamic ProgrammingDijkstra's Algorithm
LeetCode ↗

Approaches

Brute ForceOptimal
Complexity Comparison
Brute ForceOptimal Solution
Time
O(n²)
O((n + e) log n)
Space
O(1)
O(n + e)
💡

Intuition

Time O((n + e) log n)Space O(n + e)

The optimal solution uses Dijkstra's algorithm to find the shortest distances from the last node to all other nodes, then counts valid paths using a dynamic programming approach. This is efficient because it avoids redundant calculations and leverages the properties of shortest paths.

⚙️

Algorithm

4 steps
  1. 1Step 1: Use Dijkstra's algorithm to calculate the shortest distance from node n to all other nodes.
  2. 2Step 2: Create a dynamic programming array where dp[i] represents the number of restricted paths from node i to node n.
  3. 3Step 3: Traverse the nodes in reverse order (from n-1 to 1) and for each node, check its neighbors. If the distance to a neighbor is less than the current node, update dp for that neighbor.
  4. 4Step 4: Return dp[1] as the result.
solution.py35 lines
1# Full working Python code
2import heapq
3from collections import defaultdict
4
5def countRestrictedPaths(n, edges):
6    graph = defaultdict(list)
7    for u, v, w in edges:
8        graph[u].append((v, w))
9        graph[v].append((u, w))
10
11    distances = dijkstra(n, graph)
12    dp = [0] * (n + 1)
13    dp[n] = 1
14
15    for node in range(n - 1, 0, -1):
16        for neighbor, weight in graph[node]:
17            if distances[node] > distances[neighbor]:
18                dp[node] += dp[neighbor]
19                dp[node] %= 10**9 + 7
20
21    return dp[1]
22
23def dijkstra(n, graph):
24    distances = [float('inf')] * (n + 1)
25    distances[n] = 0
26    min_heap = [(0, n)]
27
28    while min_heap:
29        curr_distance, node = heapq.heappop(min_heap)
30        for neighbor, weight in graph[node]:
31            if curr_distance + weight < distances[neighbor]:
32                distances[neighbor] = curr_distance + weight
33                heapq.heappush(min_heap, (distances[neighbor], neighbor))
34
35    return distances

Complexity note: The time complexity is O((n + e) log n) due to Dijkstra's algorithm, where e is the number of edges. The space complexity is O(n + e) for storing the graph and distances.

  • 1Understanding Dijkstra's algorithm is crucial for finding shortest paths in graphs.
  • 2Dynamic programming can significantly optimize counting problems by avoiding redundant calculations.

Solutions and explanations are original Tejav content. Problem titles © LeetCode — use the LeetCode button above for the full problem statement.