Minimize maximum adjacent difference in a path from top-left to bottom-right

Given a matrix arr[][] of size M * N, where arr[i][j] represents the height of the cell (row, col). The task is to find a path from top-left to bottom-right such that the value of the maximum difference in height between adjacent cells is minimum for that path.
Note: A path energy is the maximum absolute difference in heights between two consecutive cells of the path.
Examples:
Input:Â
![]()
Example matrix
Output: 1
Explanation: The path {1, 2, 1, 2, 2} has a maximum absolute difference of 1 in consecutive cells and this is better than all other possible pathsInput:Â
Â![]()
Example matrix
Output: 1
Explanation: The highlighted path is the path with minimum value of maximum adjacent difference.
An approach using DFS + Binary Search:
The idea is to use Binary search to solve this problem, if we assume a threshold value as mid, and check whether there exist a path through which we can reach to end, then that might be my answer, else look for some bigger values.
- Initialize a variable start = 0 and end = maximum possible energy required and a variable result
- Do the following while start ? end
- Calculate mid = (start + end) / 2
- Check if mid energy is valid energy required by choosing any path into the matrix
- Checking the valid energy using a valid function
- Check if we go outside the matrix or if cell(i, j) is visited or absolute difference between consecutive cells is greater than our assumed maximum energy required
- If true, then return false
- Check if we reach the bottom-right cell
- If true, then return true
- Make the current cell(i, j) visited
- Make all four direction calls and check if any path is valid
- If true, then return true.
- Otherwise, return false
- Check if we go outside the matrix or if cell(i, j) is visited or absolute difference between consecutive cells is greater than our assumed maximum energy required
- Checking the valid energy using a valid function
- If the value from a valid function returns true, then update the result and move the end to mid – 1
- Otherwise, move the start to mid + 1
- Return the result
Below is the implementation of the above approach.
C++
// C++ code to implement the above approachÂ
#include <bits/stdc++.h>using namespace std;int m, n;Â
// Function to check if there is a valid pathbool isValid(int i, int j, int x,             vector<vector<bool> >& visited,             vector<vector<int> >& arr, long long parent){    // Check if we go outside the matrix or    // cell(i, j) is visited or absolute    // difference between consecutive cell    // is greater than our assumed maximum    // energy required If true,    // then return false    if (i < 0 || j < 0 || i >= m || j >= n || visited[i][j]        || abs((long long)arr[i][j] - parent) > x)        return false;Â
    // Check if we reach at bottom-right    // cell If true, then return true    if (i == m - 1 && j == n - 1)        return true;Â
    // Make the current cell(i, j) visited    visited[i][j] = true;Â
    // Make all four direction call and    // check if any path is valid If true,    // then return true.    if (isValid(i + 1, j, x, visited, arr, arr[i][j]))        return true;    if (isValid(i - 1, j, x, visited, arr, arr[i][j]))        return true;    if (isValid(i, j + 1, x, visited, arr, arr[i][j]))        return true;    if (isValid(i, j - 1, x, visited, arr, arr[i][j]))        return true;Â
    // Otherwise, return false    return false;}Â
// Function to find the minimum value among// the maximum adjacent differencesint minimumEnergyPath(vector<vector<int> >& arr){    // Initialize a variable start = 0    // and end = maximum possible    // energy required    int start = 0, end = 10000000;Â
    // Initialize a variable result    int result = arr[0][0];Â
    // Loop to implement the binary search    while (start <= end) {        int mid = (start + end) / 2;Â
        // Initialize a visited array        // of size (m * n)        vector<vector<bool> > visited(            m, vector<bool>(n, false));Â
        // Check if mid energy is valid        // energy required by choosing any        // path into the matrix If true,        // update the result and        // move end to mid - 1        if (isValid(0, 0, mid, visited, arr, arr[0][0])) {Â
            result = mid;            end = mid - 1;        }Â
        // Otherwise, move start to mid + 1        else {Â
            start = mid + 1;        }    }Â
    // Return the result    return result;}Â
// Driver codeint main(){    vector<vector<int> > arr = {        { 1, 2, 1 },        { 2, 8, 2 },        { 2, 4, 2 },    };    m = arr.size(), n = arr[0].size();Â
    // Function Call    cout << minimumEnergyPath(arr);Â
    return 0;} |
Java
// Java code to implement the above approachÂ
import java.io.*;Â
class GFG {Â
    static int m, n;Â
    // Function to check if there is a valid path    static boolean isValid(int i, int j, int x,                           boolean[][] visited, int[][] arr,                           long parent)    {        // Check if we go outside the matrix or        // cell(i, j) is visited or absolute        // difference between consecutive cell        // is greater than our assumed maximum        // energy required If true,        // then return false        if (i < 0 || j < 0 || i >= m || j >= n            || visited[i][j]            || Math.abs(arr[i][j] - parent) > x) {            return false;        }Â
        // Check if we reach at bottom-right        // cell If true, then return true        if (i == m - 1 && j == n - 1) {            return true;        }Â
        // Make the current cell(i, j) visited        visited[i][j] = true;Â
        // Make all four direction call and        // check if any path is valid If true,        // then return true.        if (isValid(i + 1, j, x, visited, arr, arr[i][j]))            return true;        if (isValid(i - 1, j, x, visited, arr, arr[i][j]))            return true;        if (isValid(i, j + 1, x, visited, arr, arr[i][j]))            return true;        if (isValid(i, j - 1, x, visited, arr, arr[i][j]))            return true;Â
        // Otherwise, return false        return false;    }Â
    // Function to find the minimum value among    // the maximum adjacent differences    static int minimumEnergyPath(int[][] arr)    {        // Initialize a variable start = 0        // and end = maximum possible        // energy required        int start = 0, end = 10000000;Â
        // Initialize a variable result        int result = arr[0][0];Â
        // Loop to implement the binary search        while (start <= end) {            int mid = (start + end) / 2;Â
            // Initialize a visited array            // of size (m * n)            boolean[][] visited = new boolean[m][n];Â
            // Check if mid energy is valid            // energy required by choosing any            // path into the matrix If true,            // update the result and            // move end to mid - 1            if (isValid(0, 0, mid, visited, arr,                        arr[0][0])) {                result = mid;                end = mid - 1;            }Â
            // Otherwise, move start to mid + 1            else {                start = mid + 1;            }        }Â
        // Return the result        return result;    }Â
    public static void main(String[] args)    {        int[][] arr            = { { 1, 2, 1 }, { 2, 8, 2 }, { 2, 4, 2 } };Â
        m = arr.length;        n = arr[0].length;        // Function call        System.out.print(minimumEnergyPath(arr));    }}Â
// This code is contributed by lokesh. |
Python3
# Python code to implement the above approachÂ
m,n=0,0# Function to check if there is a valid pathdef isValid(i,j,x,visited,arr,parent):    # Check if we go outside the matrix or    # cell(i, j) is visited or absolute    # difference between consecutive cell    # is greater than our assumed maximum    # energy required If true,    # then return false    if(i<0 or j<0 or i>=m or j>=n or visited[i][j] or abs(arr[i][j]-parent)>x):        return False         # Check if we reach at bottom-right    # cell If true, then return true    if(i==m-1 and j==n-1):        return True         # Make the current cell(i, j) visited    visited[i][j]=True         # Make all four direction call and    # check if any path is valid If true,    # then return true.    if(isValid(i+1,j,x,visited,arr,arr[i][j])):        return True    if(isValid(i-1,j,x,visited,arr,arr[i][j])):        return True    if(isValid(i,j+1,x,visited,arr,arr[i][j])):        return True    if(isValid(i,j-1,x,visited,arr,arr[i][j])):        return True         # Otherwise, return false    return False     # Function to find the minimum value among# the maximum adjacent differencesdef minimumEnergyPath(arr):    # Initialize a variable start = 0    # and end = maximum possible    # energy required    start,end=0,10000000         # Initialize a variable result    result=arr[0][0]         # Loop to implement the binary search    while(start<=end):        mid=(start+end)//2                 # Initialize a visited array        # of size (m * n)        visited=[[False for i in range(n)] for j in range(m)]                 # Check if mid energy is valid        # energy required by choosing any        # path into the matrix If true,        # update the result and        # move end to mid - 1        if(isValid(0,0,mid,visited,arr,arr[0][0])):            result=mid            end=mid-1                 # Otherwise, move start to mid + 1        else:            start=mid+1         # Return the result    return result     # Driver Code arr=[[1,2,1],[2,8,2],[2,4,2]]m=len(arr)n=len(arr[0])Â
# Function Callprint(minimumEnergyPath(arr))Â
# This code is contributed by Pushpesh Raj. |
C#
// C# implementationusing System;Â
public class GFG {Â Â static int m, n;Â
  // Function to check if there is a valid path  public static bool isValid(int i, int j, int x,                             bool[, ] visited,                             int[, ] arr, int parent)  {         // Check if we go outside the matrix or    // cell(i, j) is visited or absolute    // difference between consecutive cell    // is greater than our assumed maximum    // energy required If true,    // then return false    if ((i < 0) || (j < 0) || (i >= m) || (j >= n)        || (visited[i, j] == true)        || (Math.Abs(arr[i, j] - parent) > x))      return false;Â
    // Check if we reach at bottom-right    // cell If true, then return true    if (i == m - 1 && j == n - 1)      return true;Â
    // Make the current cell(i, j) visited    visited[i, j] = true;Â
    // Make all four direction call and    // check if any path is valid If true,    // then return true.    if (isValid(i + 1, j, x, visited, arr, arr[i, j]))      return true;    if (isValid(i - 1, j, x, visited, arr, arr[i, j]))      return true;    if (isValid(i, j + 1, x, visited, arr, arr[i, j]))      return true;    if (isValid(i, j - 1, x, visited, arr, arr[i, j]))      return true;Â
    // Otherwise, return false    return false;  }Â
  // Function to find the minimum value among  // the maximum adjacent differences  public static int minimumEnergyPath(int[, ] arr)  {    // Initialize a variable start = 0    // and end = maximum possible    // energy required    int start = 0, end = 10000000;Â
    // Initialize a variable result    int result = arr[0, 0];Â
    // Loop to implement the binary search    while (start <= end) {      int mid = (int)((start + end) / 2);Â
      // Initialize a visited array      // of size (m * n)      bool[, ] visited = new bool[m, n];      for (int i = 0; i < m; i++) {        for (int j = 0; j < n; j++) {          visited[i, j] = false;        }      }Â
      // Check if mid energy is valid      // energy required by choosing any      // path into the matrix If true,      // update the result and      // move end to mid - 1      if (isValid(0, 0, mid, visited, arr, arr[0, 0])          == true) {Â
        result = mid;        end = mid - 1;      }Â
      // Otherwise, move start to mid + 1      else {Â
        start = mid + 1;      }    }Â
    // Return the result    return result;  }Â
  static public void Main()  {    int[, ] arr = {      { 1, 2, 1 },      { 2, 8, 2 },      { 2, 4, 2 },    };    m = arr.GetLength(0);    n = arr.GetLength(1);Â
    // Function Call    Console.WriteLine(minimumEnergyPath(arr));  }}Â
// This code is contributed by ksam24000 |
Javascript
// JavaScript code for the above approachÂ
let m, n;Â
// Function to check if there is a valid pathfunction isValid(i, j, x, visited, arr, parent){    // Check if we go outside the matrix or    // cell(i, j) is visited or absolute    // difference between consecutive cell    // is greater than our assumed maximum    // energy required If true,    // then return false    if (i < 0 || j < 0 || i >= m || j >= n || visited[i][j]        || Math.abs(arr[i][j] - parent) > x)        return false;Â
    // Check if we reach at bottom-right    // cell If true, then return true    if (i == m - 1 && j == n - 1)        return true;Â
    // make the current cell(i, j) visited    visited[i][j] = true;Â
    // make all four direction call and    // check if any path is valid If true,    // then return true.    if (isValid(i + 1, j, x, visited, arr, arr[i][j]))        return true;    if (isValid(i - 1, j, x, visited, arr, arr[i][j]))        return true;    if (isValid(i, j + 1, x, visited, arr, arr[i][j]))        return true;    if (isValid(i, j - 1, x, visited, arr, arr[i][j]))        return true;Â
    // Otherwise, return false    return false;}Â
// Function to find the minimum value among// the maximum adjacent differencesfunction minimumEnergyPath(arr){    // Initialize a variable start = 0    // and end = maximum possible    // energy required    let start = 0, end = 10000000;Â
    // Initialize a variable result    let result = arr[0][0];Â
    // Loop to implement the binary search    while(start <= end) {        let mid = Math.floor((start + end) / 2);Â
        // Initialize a visited array        // of size (m * n)        let visited            = new Array(m)         for(let i = 0; i < m; i++)        {            visited[i] = new Array(n).fill(0)        }Â
        // Check if mid energy is valid        // energy required by choosing any        // path into the matrix If true,        // update the result and        // move end to mid - 1        if(isValid(0, 0, mid, visited, arr, arr[0][0])) {Â
            result = mid;            end = mid - 1;        }Â
        // Otherwise, move start to mid + 1        else {Â
            start = mid + 1;        }    }Â
    // Return the result    return result;}Â
// Driver codeÂ
let arr = [    [ 1, 2, 1 ],    [ 2, 8, 2 ],    [ 2, 4, 2 ],];m = arr.length, n = arr[0].length;Â
// Function Callconsole.log(minimumEnergyPath(arr));Â
// This code is contributed by Potta Lokesh |
1
Time Complexity: O(log2(K) * (M*N)), where K is the maximum element in the matrix and M, and N are the number of rows and columns in the given matrix respectively.
Auxiliary Space: O(M * N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



