Open In App

Find the longest path in a matrix with given constraints

Given a n*n matrix where all numbers are distinct, find the maximum length path (starting from any cell) such that all cells along the path are in increasing order with a difference of 1.
We can move in 4 directions from a given cell (i, j), i.e., we can move to (i+1, j) or (i, j+1) or (i-1, j) or (i, j-1) with the condition that the adjacent cells have a difference of 1.

Example:

```Input:  mat[][] = {{1, 2, 9}
{5, 3, 8}
{4, 6, 7}}
Output: 4
The longest path is 6-7-8-9. ```

The idea is simple, we calculate longest path beginning with every cell. Once we have computed longest for all cells, we return maximum of all longest paths. One important observation in this approach is many overlapping sub-problems. Therefore this problem can be optimally solved using Dynamic Programming.

Algorithm:

Step 1: Initialize a matrix and set its size to n x n.
Step 2: Define a function “findLongestFromACell” that takes in a cell’s row and column index, the matrix, and a lookup table. If the cell is out of                     bounds or the subproblem has already been solved, return 0 or the previously calculated value in the lookup table, respectively.
Step 3: Define four integer variables to store the length of the path in each of the four possible directions. Check if the adjacent cell in each                          direction satisfies the constraints and if so, recursively call the function for that cell and update the corresponding direction’s length                           variable.
Step 4: Return the maximum length of the four directions plus one, and store it in the lookup table.
Step 5: Define a function “finLongestOverAll” that takes in the matrix. Initialize a result variable to 1 and a lookup table as a two-dimensional array              of size n x n, filled with -1.
Step 6: For each cell in the matrix, call “findLongestFromACell” and update the result as needed.
Step 7: Return the result.

Below is Dynamic Programming based implementation that uses a lookup table dp[][] to check if a problem is already solved or not.

C++

 `// C++ program to find the longest path in a matrix``// with given constraints``#include ``#define n 3``using` `namespace` `std;` `// Returns length of the longest path beginning with``// mat[i][j]. This function mainly uses lookup table``// dp[n][n]``int` `findLongestFromACell(``int` `i, ``int` `j, ``int` `mat[n][n],``                         ``int` `dp[n][n])``{``    ``if` `(i < 0 || i >= n || j < 0 || j >= n)``        ``return` `0;` `    ``// If this subproblem is already solved``    ``if` `(dp[i][j] != -1)``        ``return` `dp[i][j];` `    ``// To store the path lengths in all the four directions``    ``int` `x = INT_MIN, y = INT_MIN, z = INT_MIN, w = INT_MIN;` `    ``// Since all numbers are unique and in range from 1 to``    ``// n*n, there is atmost one possible direction from any``    ``// cell``    ``if` `(j < n - 1 && ((mat[i][j] + 1) == mat[i][j + 1]))``        ``x = 1 + findLongestFromACell(i, j + 1, mat, dp);` `    ``if` `(j > 0 && (mat[i][j] + 1 == mat[i][j - 1]))``        ``y = 1 + findLongestFromACell(i, j - 1, mat, dp);` `    ``if` `(i > 0 && (mat[i][j] + 1 == mat[i - 1][j]))``        ``z = 1 + findLongestFromACell(i - 1, j, mat, dp);` `    ``if` `(i < n - 1 && (mat[i][j] + 1 == mat[i + 1][j]))``        ``w = 1 + findLongestFromACell(i + 1, j, mat, dp);` `    ``// If none of the adjacent fours is one greater we will``    ``// take 1 otherwise we will pick maximum from all the``    ``// four directions``    ``return` `dp[i][j] = max({x, y, z, w, 1});``}` `// Returns length of the longest path beginning with any``// cell``int` `finLongestOverAll(``int` `mat[n][n])``{``    ``int` `result = 1; ``// Initialize result` `    ``// Create a lookup table and fill all entries in it as``    ``// -1``    ``int` `dp[n][n];``    ``memset``(dp, -1, ``sizeof` `dp);` `    ``// Compute longest path beginning from all cells``    ``for` `(``int` `i = 0; i < n; i++) {``        ``for` `(``int` `j = 0; j < n; j++) {``            ``if` `(dp[i][j] == -1)``                ``findLongestFromACell(i, j, mat, dp);` `            ``// Update result if needed``            ``result = max(result, dp[i][j]);``        ``}``    ``}` `    ``return` `result;``}` `// Driver program``int` `main()``{``    ``int` `mat[n][n]``        ``= { { 1, 2, 9 }, { 5, 3, 8 }, { 4, 6, 7 } };``    ``cout << ``"Length of the longest path is "``         ``<< finLongestOverAll(mat);``    ``return` `0;``}`

Java

 `// Java program to find the longest path in a matrix``// with given constraints` `class` `GFG {``    ``public` `static` `int` `n = ``3``;` `    ``// Function that returns length of the longest path``    ``// beginning with mat[i][j]``    ``// This function mainly uses lookup table dp[n][n]``    ``static` `int` `findLongestFromACell(``int` `i, ``int` `j,``                                    ``int` `mat[][], ``int` `dp[][])``    ``{``        ``// Base case``        ``if` `(i < ``0` `|| i >= n || j < ``0` `|| j >= n)``            ``return` `0``;` `        ``// If this subproblem is already solved``        ``if` `(dp[i][j] != -``1``)``            ``return` `dp[i][j];` `        ``// To store the path lengths in all the four``        ``// directions``        ``int` `x = Integer.MIN_VALUE, y = Integer.MIN_VALUE,``            ``z = Integer.MIN_VALUE, w = Integer.MIN_VALUE;``        ``// Since all numbers are unique and in range from 1``        ``// to n*n, there is atmost one possible direction``        ``// from any cell``        ``if` `(j < n - ``1` `&& ((mat[i][j] + ``1``) == mat[i][j + ``1``]))``            ``x = dp[i][j]``                ``= ``1``                  ``+ findLongestFromACell(i, j + ``1``, mat, dp);` `        ``if` `(j > ``0` `&& (mat[i][j] + ``1` `== mat[i][j - ``1``]))``            ``y = dp[i][j]``                ``= ``1``                  ``+ findLongestFromACell(i, j - ``1``, mat, dp);` `        ``if` `(i > ``0` `&& (mat[i][j] + ``1` `== mat[i - ``1``][j]))``            ``z = dp[i][j]``                ``= ``1``                  ``+ findLongestFromACell(i - ``1``, j, mat, dp);` `        ``if` `(i < n - ``1` `&& (mat[i][j] + ``1` `== mat[i + ``1``][j]))``            ``w = dp[i][j]``                ``= ``1``                  ``+ findLongestFromACell(i + ``1``, j, mat, dp);` `        ``// If none of the adjacent fours is one greater we``        ``// will take 1 otherwise we will pick maximum from``        ``// all the four directions``        ``return` `dp[i][j]``            ``= Math.max(``                ``x,``                ``Math.max(y, Math.max(z, Math.max(w, ``1``))));``    ``}` `    ``// Function that returns length of the longest path``    ``// beginning with any cell``    ``static` `int` `finLongestOverAll(``int` `mat[][])``    ``{``        ``// Initialize result``        ``int` `result = ``1``;` `        ``// Create a lookup table and fill all entries in it``        ``// as -1``        ``int``[][] dp = ``new` `int``[n][n];``        ``for` `(``int` `i = ``0``; i < n; i++)``            ``for` `(``int` `j = ``0``; j < n; j++)``                ``dp[i][j] = -``1``;` `        ``// Compute longest path beginning from all cells``        ``for` `(``int` `i = ``0``; i < n; i++) {``            ``for` `(``int` `j = ``0``; j < n; j++) {``                ``if` `(dp[i][j] == -``1``)``                    ``findLongestFromACell(i, j, mat, dp);` `                ``// Update result if needed``                ``result = Math.max(result, dp[i][j]);``            ``}``        ``}` `        ``return` `result;``    ``}` `    ``// driver program``    ``public` `static` `void` `main(String[] args)``    ``{``        ``int` `mat[][]``            ``= { { ``1``, ``2``, ``9` `}, { ``5``, ``3``, ``8` `}, { ``4``, ``6``, ``7` `} };``        ``System.out.println(``"Length of the longest path is "``                           ``+ finLongestOverAll(mat));``    ``}``}` `// Contributed by Pramod Kumar`

Python3

 `# Python3 program to find the longest path in a matrix``# with given constraints` `n ``=` `3``# Returns length of the longest path beginning with mat[i][j].``# This function mainly uses lookup table dp[n][n]`  `def` `findLongestFromACell(i, j, mat, dp):``    ``# Base case``    ``if` `(i < ``0` `or` `i >``=` `n ``or` `j < ``0` `or` `j >``=` `n):``        ``return` `0` `    ``# If this subproblem is already solved``    ``if` `(dp[i][j] !``=` `-``1``):``        ``return` `dp[i][j]` `    ``# To store the path lengths in all the four directions``    ``x, y, z, w ``=` `-``1``, ``-``1``, ``-``1``, ``-``1` `    ``# Since all numbers are unique and in range from 1 to n * n,``    ``# there is atmost one possible direction from any cell``    ``if` `(j < n``-``1` `and` `((mat[i][j] ``+` `1``) ``=``=` `mat[i][j ``+` `1``])):``        ``x ``=` `1` `+` `findLongestFromACell(i, j ``+` `1``, mat, dp)` `    ``if` `(j > ``0` `and` `(mat[i][j] ``+` `1` `=``=` `mat[i][j``-``1``])):``        ``y ``=` `1` `+` `findLongestFromACell(i, j``-``1``, mat, dp)` `    ``if` `(i > ``0` `and` `(mat[i][j] ``+` `1` `=``=` `mat[i``-``1``][j])):``        ``z ``=` `1` `+` `findLongestFromACell(i``-``1``, j, mat, dp)` `    ``if` `(i < n``-``1` `and` `(mat[i][j] ``+` `1` `=``=` `mat[i ``+` `1``][j])):``        ``w ``=` `1` `+` `findLongestFromACell(i ``+` `1``, j, mat, dp)` `    ``# If none of the adjacent fours is one greater we will take 1``    ``# otherwise we will pick maximum from all the four directions``    ``dp[i][j] ``=` `max``(x, ``max``(y, ``max``(z, ``max``(w, ``1``))))``    ``return` `dp[i][j]`  `# Returns length of the longest path beginning with any cell``def` `finLongestOverAll(mat):``    ``result ``=` `1`  `# Initialize result` `    ``# Create a lookup table and fill all entries in it as -1``    ``dp ``=` `[[``-``1` `for` `i ``in` `range``(n)]``for` `i ``in` `range``(n)]` `    ``# Compute longest path beginning from all cells``    ``for` `i ``in` `range``(n):``        ``for` `j ``in` `range``(n):``            ``if` `(dp[i][j] ``=``=` `-``1``):``                ``findLongestFromACell(i, j, mat, dp)``            ``# Update result if needed``            ``result ``=` `max``(result, dp[i][j])``    ``return` `result`  `# Driver program``mat ``=` `[[``1``, ``2``, ``9``],``       ``[``5``, ``3``, ``8``],``       ``[``4``, ``6``, ``7``]]``print``(``"Length of the longest path is "``, finLongestOverAll(mat))` `# this code is improved by sahilshelangia`

Javascript

 ``

C#

 `// C# program to find the longest path``// in a matrix with given constraints``using` `System;` `class` `GFG {``    ``public` `static` `int` `n = 3;` `    ``// Function that returns length of``    ``// the longest path beginning with mat[i][j]``    ``// This function mainly uses lookup``    ``// table dp[n][n]``    ``public` `static` `int` `findLongestFromACell(``int` `i, ``int` `j,``                                           ``int``[][] mat,``                                           ``int``[][] dp)``    ``{``        ``// Base case``        ``if` `(i < 0 || i >= n || j < 0 || j >= n) {``            ``return` `0;``        ``}` `        ``// If this subproblem is``        ``// already solved``        ``if` `(dp[i][j] != -1) {``            ``return` `dp[i][j];``        ``}` `        ``// To store the path lengths in all the four``        ``// directions``        ``int` `x = ``int``.MinValue, y = ``int``.MinValue,``            ``z = ``int``.MinValue, w = ``int``.MinValue;` `        ``// Since all numbers are unique and``        ``// in range from 1 to n*n, there is``        ``// atmost one possible direction``        ``// from any cell``        ``if` `(j < n - 1``            ``&& ((mat[i][j] + 1) == mat[i][j + 1])) {``            ``x = dp[i][j]``                ``= 1``                  ``+ findLongestFromACell(i, j + 1, mat, dp);``        ``}` `        ``if` `(j > 0 && (mat[i][j] + 1 == mat[i][j - 1])) {``            ``y = dp[i][j]``                ``= 1``                  ``+ findLongestFromACell(i, j - 1, mat, dp);``        ``}` `        ``if` `(i > 0 && (mat[i][j] + 1 == mat[i - 1][j])) {``            ``z = dp[i][j]``                ``= 1``                  ``+ findLongestFromACell(i - 1, j, mat, dp);``        ``}` `        ``if` `(i < n - 1 && (mat[i][j] + 1 == mat[i + 1][j])) {``            ``w = dp[i][j]``                ``= 1``                  ``+ findLongestFromACell(i + 1, j, mat, dp);``        ``}` `        ``// If none of the adjacent fours is one greater we``        ``// will take 1 otherwise we will pick maximum from``        ``// all the four directions``        ``dp[i][j] = Math.Max(``            ``x, Math.Max(y, Math.Max(z, Math.Max(w, 1))));``        ``return` `dp[i][j];``    ``}` `    ``// Function that returns length of the``    ``// longest path beginning with any cell``    ``public` `static` `int` `finLongestOverAll(``int``[][] mat)``    ``{``        ``// Initialize result``        ``int` `result = 1;` `        ``// Create a lookup table and fill``        ``// all entries in it as -1``        ``int``[][] dp``            ``= RectangularArrays.ReturnRectangularIntArray(``                ``n, n);``        ``for` `(``int` `i = 0; i < n; i++) {``            ``for` `(``int` `j = 0; j < n; j++) {``                ``dp[i][j] = -1;``            ``}``        ``}` `        ``// Compute longest path beginning``        ``// from all cells``        ``for` `(``int` `i = 0; i < n; i++) {``            ``for` `(``int` `j = 0; j < n; j++) {``                ``if` `(dp[i][j] == -1) {``                    ``findLongestFromACell(i, j, mat, dp);``                ``}` `                ``// Update result if needed``                ``result = Math.Max(result, dp[i][j]);``            ``}``        ``}` `        ``return` `result;``    ``}` `    ``public` `static` `class` `RectangularArrays {``        ``public` `static` `int``[][] ReturnRectangularIntArray(``            ``int` `size1, ``int` `size2)``        ``{``            ``int``[][] newArray = ``new` `int``[size1][];``            ``for` `(``int` `array1 = 0; array1 < size1; array1++) {``                ``newArray[array1] = ``new` `int``[size2];``            ``}` `            ``return` `newArray;``        ``}``    ``}` `    ``// Driver Code``    ``public` `static` `void` `Main(``string``[] args)``    ``{``        ``int``[][] mat = ``new` `int``[][] { ``new` `int``[] { 1, 2, 9 },``                                    ``new` `int``[] { 5, 3, 8 },``                                    ``new` `int``[] { 4, 6, 7 } };``        ``Console.WriteLine(``"Length of the longest path is "``                          ``+ finLongestOverAll(mat));``    ``}``}` `// This code is contributed by Shrikant13`

Output

`Length of the longest path is 4`

Time complexity of the above solution is O(n2). It may seem more at first look. If we take a closer look, we can notice that all values of dp[i][j] are computed only once.
Auxiliary Space: O(N x N), since N x N extra space has been taken.