class Solution:
def longestIncreasingPath(self, matrix):
if not matrix or not matrix[0]:
return 0
m, n = len(matrix), len(matrix[0])
memo = [[0]*n for _ in range(m)]
def dfs(x, y):
if memo[x][y]:
return memo[x][y]
val = matrix[x][y]
max_len = 1
for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]:
nx, ny = x+dx, y+dy
if 0<=nx<m and 0<=ny<n and matrix[nx][ny] > val:
max_len = max(max_len, 1 + dfs(nx, ny))
memo[x][y] = max_len
return max_len
return max(dfs(i, j) for i in range(m) for j in range(n))
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
int m = matrix.size(), n = matrix[0].size();
vector<vector<int>> memo(m, vector<int>(n, 0));
int res = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
res = max(res, dfs(matrix, memo, i, j));
}
}
return res;
}
private:
int dfs(vector<vector<int>>& matrix, vector<vector<int>>& memo, int x, int y) {
if (memo[x][y]) return memo[x][y];
int m = matrix.size(), n = matrix[0].size(), val = matrix[x][y], max_len = 1;
vector<pair<int, int>> dirs = {{-1,0},{1,0},{0,-1},{0,1}};
for (auto d : dirs) {
int nx = x + d.first, ny = y + d.second;
if (nx >= 0 && nx < m && ny >= 0 && ny < n && matrix[nx][ny] > val) {
max_len = max(max_len, 1 + dfs(matrix, memo, nx, ny));
}
}
memo[x][y] = max_len;
return max_len;
}
};
class Solution {
private int[][] memo;
private int m, n;
private int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};
public int longestIncreasingPath(int[][] matrix) {
if (matrix == null || matrix.length == 0) return 0;
m = matrix.length; n = matrix[0].length;
memo = new int[m][n];
int res = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
res = Math.max(res, dfs(matrix, i, j));
}
}
return res;
}
private int dfs(int[][] matrix, int x, int y) {
if (memo[x][y] != 0) return memo[x][y];
int maxLen = 1;
for (int[] dir : dirs) {
int nx = x + dir[0], ny = y + dir[1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && matrix[nx][ny] > matrix[x][y]) {
maxLen = Math.max(maxLen, 1 + dfs(matrix, nx, ny));
}
}
memo[x][y] = maxLen;
return maxLen;
}
}
var longestIncreasingPath = function(matrix) {
if (!matrix || !matrix.length || !matrix[0].length) return 0;
const m = matrix.length, n = matrix[0].length;
const memo = Array.from({length: m}, () => Array(n).fill(0));
const dfs = (x, y) => {
if (memo[x][y]) return memo[x][y];
let maxLen = 1;
const dirs = [[-1,0],[1,0],[0,-1],[0,1]];
for (const [dx, dy] of dirs) {
const nx = x + dx, ny = y + dy;
if (nx >= 0 && nx < m && ny >= 0 && ny < n && matrix[nx][ny] > matrix[x][y]) {
maxLen = Math.max(maxLen, 1 + dfs(nx, ny));
}
}
memo[x][y] = maxLen;
return maxLen;
};
let res = 0;
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
res = Math.max(res, dfs(i, j));
}
}
return res;
};
Given a 2D integer matrix matrix
, find the length of the longest increasing path in matrix
. From each cell, you can move in four directions: up, down, left, or right. You may not move diagonally or move outside the boundary of the matrix. You cannot revisit the same cell within a single path. A path is considered increasing if each next cell has a strictly higher value than the previous one.
At first glance, the problem resembles finding the longest path in a grid, with the restriction that each move must go to a strictly larger value. The brute-force approach would be to start a DFS from every cell, exploring all possible increasing paths, and tracking the maximum length found. However, this quickly becomes inefficient due to repeated exploration of the same subproblems from different starting points.
To optimize, we observe that the result of the longest increasing path starting from a particular cell only depends on the values of its neighbors and not on the path taken to reach the cell. This means we can cache or "memoize" the result for each cell, so that we do not recompute it if we encounter the cell again in a different DFS traversal.
This insight shifts our approach from brute-force to a dynamic programming solution with memoization, drastically improving performance.
memo
) with the same dimensions as matrix
to store the length of the longest increasing path starting from each cell.Consider the following matrix:
[ [9, 9, 4], [6, 6, 8], [2, 1, 1] ]
The Longest Increasing Path in a Matrix problem is best solved with DFS and memoization. By caching the result of each subproblem, we avoid redundant computation and ensure each cell is visited only once. This transforms a potentially exponential brute-force approach into an efficient linear-time solution, making it both elegant and practical for large matrices.