Longest Increasing Path in Matrix (original) (raw)
Given a **matrix with n rows and m columns. The task is to find the length of the longest increasing path in the matrix, here increasing path means that the value in the specified path increases. For example, if a path of length k has values a1, a2, a3, .... ak, then for every i from **[2,k] this condition must hold **ai > ai-1. No cell should be revisited in the path.
From each cell, we can either move in four directions: **left, right, up, or down. We are not allowed to move diagonally or move outside the boundary.
**Examples:
**Input: matrix[][] = [[1 2 3],
[4 5 6],
[7 8 9]]
**Output: 5
**Explanation: One such path is1 → 2 → 3 → 6 → 9, where each number is strictly greater than the previous and movement is allowed in four directions (up, down, left, right).
Input: matrix[][] = [[3 4 5],
[6 2 6],
[2 2 1]]
Output: 4
Explanation: The longest increasing path is 3→4→**5 →6, where each number is strictly greater than the previous and movement is allowed in four directions (up, down, left, right).
Table of Content
- [Naive Approach] Using Recursion - O(4^(m*n)) Time and O(m*n) Space
- [Expected Approach 1] Using Top-Down DP (Memoization) - O(m*n) Time and O(m*n) Space
- [Expected Approach 2] Using Kahn's algorithm - O(m*n) Time and O(n*m) Space
[Naive Approach] Using Recursion - O(4^(m*n)) Time and O(m*n) Space
The idea is to **recursively check the longest paths from each cell. For each cell, initialize the answer to 1. Recursively process all the **four directions (first check if the cells are valid and then check that their value is greater than current cell value) and set answer to the **maximum of the four directions. Return the calculated answer.
C++ `
// Recursive c++ program to find // longest incresing path in matrix #include <bits/stdc++.h> using namespace std;
// Function which checks if the cell is valid // and its value is greater than previous cell. bool validCell(int i, int j, vector<vector> &matrix, int n, int m, int prev) { if (i >= 0 && i < n && j >= 0 && j < m && matrix[i][j] > prev) return true; return false; }
int pathRecur(int i, int j, vector<vector> &matrix, int n, int m) {
// include current cell in answer
int ans = 1;
// direction vector to move in 4 directions
vector<vector<int>> dir =
{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (auto d : dir) {
int x = i + d[0], y = j + d[1];
if (validCell(x, y, matrix, n, m, matrix[i][j])) {
ans = max(ans, 1 + pathRecur(x, y, matrix, n, m));
}
}
return ans;}
int longIncPath(vector<vector> &matrix){
int n = matrix.size();
int m = matrix[0].size();
int ans = 0;
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = max(ans, pathRecur(i, j, matrix, n, m));
}
}
return ans;}
int main() {
vector<vector<int>> matrix =
{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
cout << longIncPath(matrix) << endl;
return 0;}
Java
// Java program to find // longest increasing path in matrix
import java.util.*;
class GfG {
// Function which checks if the cell is valid
// and its value is greater than previous cell.
static boolean validCell(int i, int j, int[][] matrix,
int n, int m, int prev) {
return (i >= 0 && i < n && j >= 0 && j < m
&& matrix[i][j] > prev);
}
static int pathRecur(int i, int j, int[][] matrix,
int n, int m) {
// include current cell in answer
int ans = 1;
// direction vectors to move in 4 directions
int[][] dir
= { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int[] d : dir) {
int x = i + d[0], y = j + d[1];
// Check if the cell is valid
if (validCell(x, y, matrix, n, m,
matrix[i][j])) {
ans = Math.max(
ans, 1 + pathRecur(x, y, matrix, n, m));
}
}
return ans;
}
static int longIncPath(int[][] matrix) {
int ans = 0;
int n = matrix.length;
int m = matrix[0].length;
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.max(
ans, pathRecur(i, j, matrix, n, m));
}
}
return ans;
}
public static void main(String[] args) {
int[][] matrix
= { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
System.out.println(longIncPath(matrix));
}}
Python
Python program to find
longest increasing path in matrix
def validCell(i, j, matrix, n, m, prev):
return i >= 0 and i < n and j >= 0 and j < m
and matrix[i][j] > prev
def pathRecur(i, j, matrix, n, m):
# include current cell in answer
ans = 1
# direction vectors to move in 4 directions
dir = [(1, 0), (-1, 0), (0, 1), (0, -1)]
for d in dir:
x, y = i + d[0], j + d[1]
# Check if the cell is valid
if validCell(x, y, matrix, n, m, matrix[i][j]):
ans = max(ans, 1 + pathRecur(x, y, matrix, n, m))
return ansdef longIncPath(matrix): ans = 0 n = len(matrix) m = len(matrix[0]) # Check longest increasing path # for each cell. for i in range(n): for j in range(m): ans = max(ans, pathRecur(i, j, matrix, n, m))
return ansif name == "main":
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(longIncPath(matrix))C#
// C# program to find // longest increasing path in matrix
using System;
class GfG {
// Function which checks if the cell is valid
// and its value is greater than previous cell.
static bool validCell(int i, int j, int[, ] matrix,
int n, int m, int prev) {
return (i >= 0 && i < n && j >= 0 && j < m
&& matrix[i, j] > prev);
}
static int pathRecur(int i, int j, int[, ] matrix,
int n, int m) {
// include current cell in answer
int ans = 1;
// direction vectors to move in 4 directions
int[, ] dir
= { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int d = 0; d < 4; d++) {
int x = i + dir[d, 0], y = j + dir[d, 1];
// Check if the cell is valid
if (validCell(x, y, matrix, n, m,
matrix[i, j])) {
ans = Math.Max(
ans, 1 + pathRecur(x, y, matrix, n, m));
}
}
return ans;
}
static int longIncPath(int[, ] matrix) {
int ans = 0;
int n = matrix.GetLength(0);
int m = matrix.GetLength(1);
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.Max(
ans, pathRecur(i, j, matrix, n, m));
}
}
return ans;
}
static void Main(string[] args) {
int[, ] matrix
= { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Console.WriteLine(longIncPath(matrix));
}}
JavaScript
// JavaScript program to find // longest increasing path in matrix
function validCell(i, j, matrix, n, m, prev) { return (i >= 0 && i < n && j >= 0 && j < m && matrix[i][j] > prev); }
function pathRecur(i, j, matrix, n, m) {
// include current cell in answer
let ans = 1;
// direction vectors to move in
// 4 directions
const dir =
[ [ 1, 0 ], [ -1, 0 ], [ 0, 1 ], [ 0, -1 ] ];
for (const d of dir) {
const x = i + d[0], y = j + d[1];
// Check if the cell is valid
if (validCell(x, y, matrix, n, m, matrix[i][j])) {
ans = Math.max(
ans, 1 + pathRecur(x, y, matrix, n, m));
}
}
return ans;}
function longIncPath(matrix) { let ans = 0; let n = matrix.length; let m = matrix[0].length; // Check longest increasing path // for each cell. for (let i = 0; i < n; i++) { for (let j = 0; j < m; j++) { ans = Math.max(ans, pathRecur(i, j, matrix, n, m)); } }
return ans;}
const matrix = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ];
console.log(longIncPath(matrix));
`
[Expected Approach 1] Using Top-Down DP (Memoization****)** - O(m*n) Time and O(m*n) Space
The idea is to use Dynamic Programming in the first approach. For a given cell, store its result in the **2D array so that if this cell is again called, we can simply return the value stored in the 2D array.
**1. Optimal Substructure:
The longest increasing path from a given cell depends on the optimal solutions of its four neighboring cells. By combining these optimal substructures, we can efficiently calculate longest increasing path starting from given cell.**2. Overlapping Subproblems:
We can observe that a cell can be a neighbour of multiple cells and multiple calls can be made for it.
- There are two parameters: **i and **j (cell indices) that changes in the recursive solution. So create a 2D array of size n*m (where n is the number of rows and m is the number of columns in the matrix).
- Initiate all values in the 2D array as -1 to indicate nothing is computed yet.
- Check the longest increasing path for each cell (**i, j). If the value in array for given cell is -1, then only make the recursive calls for the neighboring cells and store the result in the array. Otherwise, simply return the value stored in the array. C++ `
// c++ program to find // longest incresing path in matrix #include <bits/stdc++.h> using namespace std;
// Function which checks if the cell is valid // and its value is greater than previous cell. bool validCell(int i, int j, vector<vector> &matrix, int prev) { if (i >= 0 && i < matrix.size() && j >= 0 && j < matrix[0].size() && matrix[i][j] > prev) return true; return false; }
int pathRecur(int i, int j, vector<vector> &matrix, vector<vector> &memo) {
// If answer exists in memo table.
if (memo[i][j] != -1)
return memo[i][j];
// include current cell in answer
int ans = 1;
// direction vector to move in 4 directions
vector<vector<int>> dir =
{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (auto d : dir) {
int x = i + d[0], y = j + d[1];
// Check if the cell is valid
if (validCell(x, y, matrix, matrix[i][j])) {
ans = max(ans, 1 + pathRecur(x, y, matrix, memo));
}
}
// Memoize the answer and return it.
return memo[i][j] = ans;}
int longIncPath(vector<vector> &matrix, int n, int m) { int ans = 0;
// Initialize dp table
vector<vector<int>> memo(n, vector<int>(m, -1));
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = max(ans, pathRecur(i, j, matrix, memo));
}
}
return ans;}
int main() { int n = 3, m = 3; vector<vector> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
cout << longIncPath(matrix, n, m) << endl;
return 0;}
Java
// Java program to find // longest increasing path in matrix
class GfG {
// Function which checks if the cell is valid
// and its value is greater than previous cell.
static boolean validCell(int i, int j, int[][] matrix,
int prev) {
return (i >= 0 && i < matrix.length && j >= 0
&& j < matrix[0].length
&& matrix[i][j] > prev);
}
static int pathRecur(int i, int j, int[][] matrix,
int[][] memo) {
// If answer exists in memo table.
if (memo[i][j] != -1)
return memo[i][j];
// include current cell in answer
int ans = 1;
// direction vector to move in 4 directions
int[][] dir
= { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int[] d : dir) {
int x = i + d[0], y = j + d[1];
// Check if the cell is valid
if (validCell(x, y, matrix, matrix[i][j])) {
ans = Math.max(
ans, 1 + pathRecur(x, y, matrix, memo));
}
}
// Memoize the answer and return it.
memo[i][j] = ans;
return ans;
}
static int longIncPath(int[][] matrix, int n,
int m) {
int ans = 0;
// Initialize dp table
int[][] memo = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
memo[i][j] = -1;
}
}
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.max(
ans, pathRecur(i, j, matrix, memo));
}
}
return ans;
}
public static void main(String[] args) {
int n = 3, m = 3;
int[][] matrix
= { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
System.out.println(longIncPath(matrix, n, m));
}}
Python
Python program to find
longest increasing path in matrix
def validCell(i, j, matrix, prev):
return i >= 0 and i < len(matrix) and j >= 0 and
j < len(matrix[0]) and matrix[i][j] > prev
def pathRecur(i, j, matrix, memo):
# If answer exists in memo table.
if memo[i][j] != -1:
return memo[i][j]
# include current cell in answer
ans = 1
# direction vectors to move in
# 4 directions
dir = [(1, 0), (-1, 0), (0, 1), (0, -1)]
for d in dir:
x, y = i + d[0], j + d[1]
# Check if the cell is valid
if validCell(x, y, matrix, matrix[i][j]):
ans = max(ans, 1 + pathRecur(x, y, matrix, memo))
# Memoize the answer and return it.
memo[i][j] = ans
return ansdef longIncPath(matrix, n, m): ans = 0
# Initialize dp table
memo = [[-1] * m for _ in range(n)]
# Check longest increasing path
# for each cell.
for i in range(n):
for j in range(m):
ans = max(ans, pathRecur(i, j, matrix, memo))
return ansif name == "main": n, m = 3, 3 matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(longIncPath(matrix, n, m))C#
// C# program to find // longest increasing path in matrix
using System;
class GfG {
// Function which checks if the cell is valid
// and its value is greater than previous cell.
static bool validCell(int i, int j, int[, ] matrix,
int prev) {
return (i >= 0 && i < matrix.GetLength(0) && j >= 0
&& j < matrix.GetLength(1)
&& matrix[i, j] > prev);
}
static int pathRecur(int i, int j, int[, ] matrix,
int[, ] memo) {
// If answer exists in memo table.
if (memo[i, j] != -1)
return memo[i, j];
// include current cell in answer
int ans = 1;
// direction vectors to move in 4 directions
int[, ] dir
= { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int d = 0; d < 4; d++) {
int x = i + dir[d, 0], y = j + dir[d, 1];
// Check if the cell is valid
if (validCell(x, y, matrix, matrix[i, j])) {
ans = Math.Max(
ans, 1 + pathRecur(x, y, matrix, memo));
}
}
// Memoize the answer
// and return it.
memo[i, j] = ans;
return ans;
}
static int longIncPath(int[, ] matrix, int n, int m) {
int ans = 0;
// Initialize dp table
int[, ] memo = new int[n, m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
memo[i, j] = -1;
}
}
// Check longest increasing path
// for each cell.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.Max(
ans, pathRecur(i, j, matrix, memo));
}
}
return ans;
}
static void Main(string[] args) {
int n = 3, m = 3;
int[, ] matrix
= { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Console.WriteLine(longIncPath(matrix, n, m));
}}
JavaScript
// JavaScript program to find // longest increasing path in matrix
function validCell(i, j, matrix, prev) { return i >= 0 && i < matrix.length && j >= 0 && j < matrix[0].length && matrix[i][j] > prev; }
function pathRecur(i, j, matrix, memo) {
// If answer exists in memo table.
if (memo[i][j] !== -1)
return memo[i][j];
// include current cell in answer
let ans = 1;
// direction vectors to move in 4 directions
const dir =
[ [ 1, 0 ], [ -1, 0 ], [ 0, 1 ], [ 0, -1 ] ];
for (const d of dir) {
const x = i + d[0], y = j + d[1];
// Check if the cell is valid
if (validCell(x, y, matrix, matrix[i][j])) {
ans = Math.max(
ans, 1 + pathRecur(x, y, matrix, memo));
}
}
// Memoize the answer and return it.
memo[i][j] = ans;
return ans;}
function longIncPath(matrix, n, m) {
let ans = 0;
// Initialize dp table
const memo
= Array.from({length : n},
() => Array(m).fill(-1));
// Check longest increasing path
// for each cell.
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
ans = Math.max(ans,
pathRecur(i, j, matrix, memo));
}
}
return ans;}
const n = 3, m = 3; const matrix = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ];
console.log(longIncPath(matrix, n, m));
`
[Expected Approach 2] Using Kahn's algorithm - O(m*n) Time and O(n*m) Space
Each cell in the matrix is treated as a node, and there's a directed edge from a cell to its neighboring cell if the neighbor has a **greater value. The graph formed this way is a directed acyclic graph and this problem reduces to longest path in a directed acyclic graph. We can find the longest path using Topological Sorting. We have used Kahn's algorithm in the below implementation.
To implement Kahn's algorithm, we first compute the **in-degree of each cell (i.e., the number of smaller neighbors pointing into it), which helps identify the **starting points of increasing paths (cells with in-degree 0). These starting cells are enqueued, and we perform a level-order traversal (BFS), where each level represents one step further in the increasing sequence. For each cell we process, we update the in-degree of its larger neighbors, and if their in-degree becomes 0, we enqueue them as they are ready to be part of the path. The **number of BFS levels we process gives us the **maximum path length.
C++ `
// C++ program to find the longest increasing path in a matrix using BFS (Topological Sort) #include <bits/stdc++.h> using namespace std;
// Function to find the longest increasing path in a matrix int longIncPath(vector<vector> &matrix) {
int n = matrix.size();
int m = matrix[0].size();
// Direction vectors for moving right, down, left, and up
vector<pair<int, int>> dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
// Create an in-degree matrix (used to count number
// of smaller neighbors for each cell)
vector<vector<int>> degree(n + 1, vector<int>(m + 1, 0));
// Compute the in-degree for each cell
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (auto it : dir) {
int x = i + it.first;
int y = j + it.second;
// If neighboring cell is within bounds
// and has a smaller value
if (x >= 0 && x < n && y >= 0 && y < m &&
matrix[x][y] < matrix[i][j])
degree[i][j]++; // Increase in-degree count
}
}
}
// Add all cells with in-degree 0 to the
// queue (they are starting points)
queue<pair<int, int>> q;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (degree[i][j] == 0)
q.push({i, j});
int ans = 0; // This will count the number
// of levels processed (i.e.,
// length of path)
// Perform BFS level-by-level
while (!q.empty()) {
ans++;
int l = q.size();
for (int i = 0; i < l; i++) {
int x1 = q.front().first;
int y1 = q.front().second;
q.pop();
// Explore all four directions
for (auto it : dir) {
int x = x1 + it.first;
int y = y1 + it.second;
// If neighboring cell has greater
// value (valid increasing move)
if (x >= 0 && x < n && y >= 0 && y < m &&
matrix[x][y] > matrix[x1][y1]) {
degree[x][y]--;
if (degree[x][y] == 0) {
q.push({x, y});
}
}
}
}
}
// Return the total number of BFS levels = length
// of the longest increasing path
return ans;}
int main() { vector<vector> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; cout << longIncPath(matrix) << endl; return 0; }
Java
import java.util.*;
class GfG {
// Function to find the longest increasing path in a matrix
static int longIncPath(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
// Direction vectors: right, down, left, up
int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
// In-degree matrix
int[][] degree = new int[n][m];
// Compute in-degrees
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int[] d : dir) {
int x = i + d[0];
int y = j + d[1];
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x][y] < matrix[i][j]) {
degree[i][j]++;
}
}
}
}
// Enqueue all 0 in-degree cells
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (degree[i][j] == 0) {
q.offer(new int[]{i, j});
}
}
}
int ans = 0;
// BFS level-by-level
while (!q.isEmpty()) {
ans++;
int size = q.size();
for (int i = 0; i < size; i++) {
int[] cell = q.poll();
int x1 = cell[0], y1 = cell[1];
for (int[] d : dir) {
int x = x1 + d[0];
int y = y1 + d[1];
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x][y] > matrix[x1][y1]) {
degree[x][y]--;
if (degree[x][y] == 0) {
q.offer(new int[]{x, y});
}
}
}
}
}
return ans;
}
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println(longIncPath(matrix));
}}
Python
from collections import deque
Function to find the longest increasing path in a matrix
def longIncPath(matrix): n = len(matrix) m = len(matrix[0])
# Direction vectors: right, down, left, up
dir = [(0, 1), (1, 0), (0, -1), (-1, 0)]
# In-degree matrix
degree = [[0 for _ in range(m)] for _ in range(n)]
# Compute in-degrees
for i in range(n):
for j in range(m):
for dx, dy in dir:
x, y = i + dx, j + dy
if 0 <= x < n and 0 <= y < m and matrix[x][y] < matrix[i][j]:
degree[i][j] += 1
# Enqueue all 0 in-degree cells
q = deque()
for i in range(n):
for j in range(m):
if degree[i][j] == 0:
q.append((i, j))
# BFS level-by-level
ans = 0
while q:
ans += 1
for _ in range(len(q)):
x1, y1 = q.popleft()
for dx, dy in dir:
x, y = x1 + dx, y1 + dy
if 0 <= x < n and 0 <= y < m and matrix[x][y] > matrix[x1][y1]:
degree[x][y] -= 1
if degree[x][y] == 0:
q.append((x, y))
return ansExample usage
if name == "main": matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] print(longIncPath(matrix))
C#
using System; using System.Collections.Generic;
class GfG{
// Function to find the longest increasing path in a matrix
static int longIncPath(int[,] matrix) {
int n = matrix.GetLength(0);
int m = matrix.GetLength(1);
// Direction vectors: right, down, left, up
int[,] dir = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
// In-degree matrix
int[,] degree = new int[n, m];
// Step 1: Compute in-degrees
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int d = 0; d < 4; d++) {
int x = i + dir[d, 0];
int y = j + dir[d, 1];
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x, y] < matrix[i, j]) {
degree[i, j]++;
}
}
}
}
// Step 2: Enqueue all 0 in-degree cells
Queue<(int, int)> q = new Queue<(int, int)>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (degree[i, j] == 0) {
q.Enqueue((i, j));
}
}
}
int ans = 0;
// Step 3: BFS level-by-level
while (q.Count > 0) {
ans++;
int size = q.Count;
for (int i = 0; i < size; i++) {
var (x1, y1) = q.Dequeue();
for (int d = 0; d < 4; d++) {
int x = x1 + dir[d, 0];
int y = y1 + dir[d, 1];
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x, y] > matrix[x1, y1]) {
degree[x, y]--;
if (degree[x, y] == 0) {
q.Enqueue((x, y));
}
}
}
}
}
return ans;
}
static void Main() {
int[,] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Console.WriteLine(longIncPath(matrix));
}}
JavaScript
// Function to find the longest increasing path in a matrix function longIncPath(matrix) { const n = matrix.length; const m = matrix[0].length;
// Direction vectors: right, down, left, up
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]];
// In-degree matrix
const degree = Array.from({ length: n }, () => Array(m).fill(0));
// Compute in-degrees
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
for (const [dx, dy] of dir) {
const x = i + dx;
const y = j + dy;
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x][y] < matrix[i][j]) {
degree[i][j]++;
}
}
}
}
// Enqueue all 0 in-degree cells
const q = [];
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (degree[i][j] === 0) {
q.push([i, j]);
}
}
}
// BFS level-by-level
let ans = 0;
while (q.length > 0) {
ans++;
const size = q.length;
for (let i = 0; i < size; i++) {
const [x1, y1] = q.shift();
for (const [dx, dy] of dir) {
const x = x1 + dx;
const y = y1 + dy;
if (x >= 0 && x < n && y >= 0 && y < m && matrix[x][y] > matrix[x1][y1]) {
degree[x][y]--;
if (degree[x][y] === 0) {
q.push([x, y]);
}
}
}
}
}
return ans;}
// Driver Code const matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; console.log(longIncPath(matrix));
`

