Path with minimum Effort
Problem Link : (Path With Minimum Effort)
Problem Statement
You have a 2D array heights[][] of size rows × columns. Each cell contains an integer height. You start at the top‑left cell (0,0) and want to reach the bottom‑right cell (rows‑1, columns‑1). You can move up, down, left, or right. The effort of a path is defined as the maximum absolute difference in heights between any two consecutive cells along the path.
Return the minimum possible effort required to travel from start to end.
Intuition
This problem requires minimizing the path's maximum edge cost, where each edge cost is |height[u] − height[v]|. You want the path where that maximum is as small as possible.
This matches a Dijkstra-style shortest-path problem, but instead of summing edge weights, you use:
newEffort = max(currentEffort, abs(height[u]−height[v]))
and always expand the cell with the minimum currentEffort first. That ensures when the destination is dequeued, its effort is minimized.
Algorithm (Modified Dijkstra)
-
Create a 2D array
effort[r][c], initialized to a large value (e.g.,1e9). -
Set
effort[0][0] = 0. -
Prepare a min-heap (priority queue) of
(effort, row, col)tuples. -
Push
(0, 0, 0)to the heap. -
While the heap is not empty:
-
Extract the smallest-effort tuple
(currEff, r, c). -
If
(r, c)is the destination, returncurrEff. -
For each of its four neighbors
(nr, nc)within bounds:-
Compute
stepEff = abs(height[r][c] − height[nr][nc]). -
Compute
newEff = max(currEff, stepEff). -
If
newEff < effort[nr][nc]:-
Update
effort[nr][nc] = newEff. -
Push
(newEff, nr, nc)into the heap.
-
-
-
-
If destination never extracted, return
‑1(or 0 if guaranteed reachable).
Java Code Example
class Solution {
static class Cell implements Comparable<Cell> {
int effort, r, c;
Cell(int e, int r, int c) { this.effort = e; this.r = r; this.c = c; }
public int compareTo(Cell other) { return this.effort - other.effort; }
}
public int minimumEffortPath(int[][] heights) {
int n = heights.length, m = heights[0].length;
int[][] effort = new int[n][m];
for (int[] row: effort) Arrays.fill(row, Integer.MAX_VALUE);
effort[0][0] = 0;
PriorityQueue<Cell> pq = new PriorityQueue<>();
pq.offer(new Cell(0, 0, 0));
int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
while (!pq.isEmpty()) {
Cell curr = pq.poll();
if (curr.r == n-1 && curr.c == m-1) return curr.effort;
if (curr.effort > effort[curr.r][curr.c]) continue;
for (int[] d : dirs) {
int nr = curr.r + d[0], nc = curr.c + d[1];
if (nr >= 0 && nr < n && nc >= 0 && nc < m) {
int diff = Math.abs(heights[curr.r][curr.c] - heights[nr][nc]);
int newEff = Math.max(curr.effort, diff);
if (newEff < effort[nr][nc]) {
effort[nr][nc] = newEff;
pq.offer(new Cell(newEff, nr, nc));
}
}
}
}
return -1;
}
}
Dry Run (Example)
heights = [
[1, 2, 2],
[3, 8, 2],
[5, 3, 5]
]
-
Starting at
(0,0)with effort 0. -
Move to
(1,0): step diff = 2 → newEff = 2. -
Move to others; maintain priority queue by smallest newEff.
-
Best path found:
1→3→5→3→5, where max step diff = 2. -
The algorithm returns
2
Time and Space Complexity
-
Let
R = rows,C = columns. -
There are
R×Cnodes. Each node can be pushed into the heap multiple times, but only once per better effort. -
Each pop/push is
O(log(R·C)). -
Each node’s edges (up to 4) cause checks.
-
Overall time complexity:
O((R·C) log(R·C)). -
Space complexity:
O(R·C)for effort array and priority queue.
Alternative: Binary Search + BFS
Another approach is binary-search over effort threshold E:
-
Binary search
Ebetween0and max possible height difference. -
In
canReach(E), perform BFS/DFS only traversing edges with|height diff| ≤ E. -
If BFS reaches destination, reduce search range; otherwise increase it.
-
Final answer is smallest
EpassingcanReach.
This achieves complexity O(log(maxHeight) · R · C) but is often slower in practice.
Final Notes
-
This is a grid-based shortest-path problem where the cost function is the maximum edge value along the path rather than a sum.
-
The modified Dijkstra strategy fits naturally: expanding paths by minimum current effort ensures optimality.
-
The binary-search + reachability approach is an alternative but less direct.
-
BFS-only or DFS-only without a priority structure is invalid since you must account for varying edge costs.