# Path With Minimum Effort

You are a hiker preparing for an upcoming hike. You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). You are situated in the top-left cell, (0, 0), and you hope to travel to the bottom-right cell, (rows-1, columns-1) (i.e., **0-indexed**). You can move **up**, **down**, **left**, or **right**, and you wish to find a route that requires the minimum **effort**.

A route's **effort** is the **maximum absolute difference** in heights between two consecutive cells of the route.

Return *the minimum effort required to travel from the top-left cell to the bottom-right cell.*

**Example 1:**

**Input****:** heights = [[1,2,2],[3,8,2],[5,3,5]]
**Output****:** 2
**Explanation****:** The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells.
This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3.

**Example 2:**

**Input****:** heights = [[1,2,3],[3,8,4],[5,3,5]]
**Output****:** 1
**Explanation****:** The route of [1,2,3,4,5] has a maximum absolute difference of 1 in consecutive cells, which is better than route [1,3,5,3,5].

**Example 3:**

**Input****:** heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]]
**Output****:** 0
**Explanation****:** This route does not require any effort.

**Constraints:**

rows == heights.length

columns == heights[i].length

1 <= rows, columns <= 100

1 <= heights[i][j] <= 106

**Solution:**

```
class Solution {
int m,n;
public int minimumEffortPath(int[][] heights) {
m = heights.length;
n = heights[0].length;
int[][] cost = new int[m][n];
for(int[] c: cost){
Arrays.fill(c, Integer.MAX_VALUE);
}
PriorityQueue<int[]> pq = new PriorityQueue<>((a,b) -> a[2] - b[2]);
pq.offer(new int[]{0,0,0});
int[][] dir = new int[][]{{0,1},{1,0},{-1,0},{0,-1}};
boolean[][] visited = new boolean[m][n];
visited[0][0] = true;
int maxSoFar = 0;
while(!pq.isEmpty()){
int[] curr = pq.poll();
visited[curr[0]][curr[1]] = true;
if(curr[0] == m-1 && curr[1] == n-1){
return curr[2];
}
for(int i=0; i<dir.length; i++){
int x = curr[0] + dir[i][0];
int y = curr[1] + dir[i][1];
int currCos = curr[2];
if(x>=0 && x<m && y>=0 && y<n && !visited[x][y]) {
int diff = Math.abs(heights[x][y] - heights[curr[0]][curr[1]]);
int maxDiff = Math.max(diff, currCos);
if( maxDiff < cost[x][y]) {
cost[x][y] = maxDiff;
pq.offer(new int[]{x,y,cost[x][y]});
}
}
}
}
return cost[m-1][n-1];
// O(mnlogn(mn))
}
}
```