1631. Path with Minimum Effort (Dijkstra + minHeap)¶
Edited by Charles
Medium · Python · Graph
Problem
Read the original problem on LeetCode.
The official page contains the problem statement, examples, and constraints.
Explanation, examples & other approaches
Core idea
This problem can be treated as a shortest path problem on a grid.
Original study notes follow, including intermediate snippets and earlier attempts.
Approach: Dijkstra + Min Heap¶
This problem can be treated as a shortest path problem on a grid.
Each cell (row, col) is a node, and each node can connect to at most four neighbors:
Unlike a normal graph problem, we do not need to explicitly build an adjacency list. The neighbors of each cell can be generated directly using four directions.
Graph Representation¶
For a grid with:
there are:
Each cell:
represents one node.
Instead of building an adjacency list, define four directions:
For the current node (curRow, curCol), a neighbor can be generated by:
Then check whether it is inside the grid:
Therefore, the grid itself can be viewed as an implicit graph.
Definition of Effort¶
The edge weight between two adjacent cells is their absolute height difference:
However, the effort of an entire path is not the sum of all edge weights.
It is the maximum height difference along the path.
For example:
The effort of this path is:
not:
Our goal is to find a path from the top-left cell to the bottom-right cell whose maximum edge difference is as small as possible.
minEffort Matrix¶
Create:
minEffort[row][col] represents:
The minimum possible effort required to travel from
(0, 0)to(row, col).
The starting point requires no effort:
All other cells are initially unreachable, so their efforts are initialized to infinity.
Min Heap¶
Initialize:
Each heap entry stores:
For example:
means that the current known effort required to reach (1, 2) is 3.
Since effort is the first element of the tuple, Python's heapq always pops the state with the smallest effort first.
Skip Outdated Heap States¶
A cell may be pushed into the heap multiple times if a better path is discovered later.
Therefore:
If:
then the heap entry is outdated because a better path to the same cell has already been found.
We can safely skip it.
This is the same lazy deletion idea used in standard Dijkstra.
Relaxation¶
Suppose we are currently at:
and move to:
First calculate the effort of this edge:
Since the effort of a path is the maximum edge difference along that path, the new path effort is:
Then perform relaxation:
if newEffort < minEffort[nextRow][nextCol]:
minEffort[nextRow][nextCol] = newEffort
heapq.heappush(
minHeap,
(newEffort, nextRow, nextCol)
)
If the new path gives a smaller effort, update minEffort and push the new state into the heap.
Why Dijkstra Still Works¶
Standard Dijkstra minimizes:
For example:
In this problem, we minimize:
Therefore, the relaxation formula changes to:
The rest of the Dijkstra framework remains the same.
Early Termination¶
When the bottom-right cell is popped from the min heap:
its minimum effort has already been determined.
This is because Dijkstra always processes the state with the smallest current effort first.
Therefore, we do not need to continue exploring the remaining nodes.
Finally:
Comparison with LeetCode 743¶
| 743 Network Delay Time | 1631 Minimum Effort Path | |
|---|---|---|
| Graph | Explicit graph | Grid / implicit graph |
| Node | node |
(row, col) |
| Neighbors | Adjacency list | 4 directions |
| Distance structure | 1D array | 2D matrix |
| Heap | (dist, node) |
(effort, row, col) |
| Edge weight | Given w |
Height difference |
| Path cost | Sum of weights | Maximum edge weight |
| Relaxation | curDist + weight |
max(curEffort, edgeEffort) |
The main difference is the definition of the path cost.
LeetCode 743¶
LeetCode 1631¶
The overall Dijkstra structure remains unchanged.
Complexity¶
Let:
Each cell has at most 4 edges, so:
Time Complexity¶
Each node/edge may cause a heap operation, and each heap operation costs O(log(m × n)).
Space Complexity¶
Used by:
minEffortminHeap
Study record
| Field | Value |
|---|---|
| Attempts | 1 |
| Mastery | ❚ |
| The Latest Attempt | August 28, 2026 |
Python solution¶
import heapq
class Solution:
def minimumEffortPath(self, heights: List[List[int]]) -> int:
m, n = len(heights), len(heights[0])
Directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
minEffort = [[float('inf')] * n for _ in range(m)]
minEffort[0][0] = 0
minHeap = [(0, 0, 0)]
while minHeap:
curEffort, curRow, curCol = heapq.heappop(minHeap)
if curEffort > minEffort[curRow][curCol]:
continue
if curRow == m - 1 and curCol == n - 1:
break
for rowDelta, colDelta in Directions:
nextRow = curRow + rowDelta
nextCol = curCol + colDelta
if 0 <= nextRow < m and 0 <= nextCol < n:
newEffort = max(
abs(
heights[nextRow][nextCol]
- heights[curRow][curCol]
),
curEffort
)
if newEffort < minEffort[nextRow][nextCol]:
minEffort[nextRow][nextCol] = newEffort
heapq.heappush(
minHeap,
(newEffort, nextRow, nextCol)
)
return minEffort[-1][-1]