Longest Increasing Path in a Matrix

Hard2D Grid DP · DFS + Memoization🧩 Grid DPLeetCode #329 ↗Updated

Problem

Given an m × n integer grid, find the length (number of cells) of the longest path in which every step goes up, down, left or right to a cell with a strictly larger value. Diagonal moves and wrapping around the border are not allowed.
Input[[9,9,4],[6,6,8],[2,1,1]]Output4 (1→2→6→9)
Input[[3,4,5],[3,2,6],[2,2,1]]Output4 (3→4→5→6)
Input[[1]]Output1

1 ≤ m, n ≤ 200  ·  0 ≤ matrix[i][j] ≤ 231-1

Try it yourself

Java
class Solution {
    public int longestIncreasingPath(int[][] matrix) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Because each step must go strictly uphill, a path can never revisit a cell — the grid is a DAG. So “longest path starting at (r,c)” is a fixed number: compute it once, cache it, reuse it.
PatternGrid DP

Instinct Grid moves that never loop back (right/down, row to row) plus "count or optimise the paths" - build dp[r][c] from the cells that can step in.

Memory hack Every cell asks its parents - a cell's answer comes only from the neighbours that can move into it, so fill cells in the order they arrive.

Open the Grid DP guide →

Approaches

Brute ForcePlain DFS from Every Cell

Time O(mn·3L)Space O(mn)

From each cell, recursively try all four larger neighbours and keep the best path length. No visited set is needed since values strictly increase. Each call branches up to 3 ways (it can't step back downhill) for up to L levels (L = answer), so the same sub-paths are re-explored again and again.

Java
private static final int[][] DIRS = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public int longestIncreasingPath(int[][] matrix) {
    int best = 0;
    for (int r = 0; r < matrix.length; r++)
        for (int c = 0; c < matrix[0].length; c++)
            best = Math.max(best, dfs(matrix, r, c));
    return best;
}
private int dfs(int[][] a, int r, int c) {
    int len = 1;
    for (int[] d : DIRS) {
        int x = r + d[0], y = c + d[1];
        if (x >= 0 && x < a.length && y >= 0 && y < a[0].length && a[x][y] > a[r][c])
            len = Math.max(len, 1 + dfs(a, x, y));
    }
    return len;
}

Correct, but exponential in the path length — times out on large grids.

At a glance

LevelApproachTimeSpace
Brute ForcePlain DFS from Every CellO(mn·3L)O(mn)
BetterSort Cells by Value + DPO(mn log(mn))O(mn)
OptimalDFS + MemoizationO(mn)O(mn)
Common pitfalls
  • Using ≥ instead of > — equal neighbours create cycles and infinite recursion.
  • Caching with memo == 0 as “unknown” is safe only because every answer is ≥ 1.
  • Starting DFS only from (0,0) or from minima — take the max over all cells.
Interview tips
  • Say why no visited set is needed: strictly increasing ⇒ acyclic (DAG).
  • Present memo as “longest path starting at (r,c)” — a pure function of the cell.
  • Mention Kahn's topological sort as the iterative alternative.
Pattern
DFS + memo on an implicit DAG → longest path in a grid/graph where moves follow a strict order.
My notes saved in this browser