Problem
You are given an m x n
integer matrix grid
, where you can move from a cell to any adjacent cell in all 4
directions.
Return the number of strictly increasing paths in the grid such that you can start from any cell and end at any cell. Since the answer may be very large, return it modulo 109 + 7
.
Two paths are considered different if they do not have exactly the same sequence of visited cells.
Examples
Example 1:
$$ \begin{bmatrix} 1 & 1 \\ 3 & 4 \end{bmatrix} $$
Input:
grid = [[1,1],[3,4]]
Output:
8
Explanation: The strictly increasing paths are:
- Paths with length 1: [1], [1], [3], [4].
- Paths with length 2: [1 -> 3], [1 -> 4], [3 -> 4].
- Paths with length 3: [1 -> 3 -> 4].
The total number of paths is 4 + 3 + 1 = 8.
Example 2:
$$ \begin{bmatrix} 1 \\ 2 \end{bmatrix} $$
Input:
grid = [[1],[2]]
Output:
3
Explanation: The strictly increasing paths are:
- Paths with length 1: [1], [2].
- Paths with length 2: [1 -> 2].
The total number of paths is 2 + 1 = 3.
Solution
Method 1 - Using DP
Here is the approach:
- Problem Understanding:
- You have an
m x n
matrix. - You can move from a cell to any directly adjacent cell (left, right, up, down).
- The paths need to be strictly increasing.
- The result should be the number of such paths modulo (10^9 + 7).
- You have an
- Dynamic Programming with Memoization:
- We’ll use dynamic programming to solve this problem efficiently.
- Let’s define
dp[i][j]
as the number of strictly increasing paths starting from cell(i, j)
. - We’ll need to compute
dp[i][j]
for all cells(i, j)
.
- Steps:
- Use depth-first search (DFS) to explore all possible paths starting from each cell.
- Memoize the results to avoid recomputing paths from the same cell multiple times.
- The total number of paths is the sum of paths starting from each cell in the matrix.
- Edge Cases:
- Single cell matrix.
- All elements in the matrix are the same.
Code
Java
class Solution {
private static final int MOD = 1_000_000_007;
private int m, n;
private int[][] dp, grid;
private int dfs(int i, int j) {
if (dp[i][j] != -1) return dp[i][j];
dp[i][j] = 1; // Each cell itself is a path
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] dir : directions) {
int x = i + dir[0], y = j + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] > grid[i][j]) {
dp[i][j] = (dp[i][j] + dfs(x, y)) % MOD;
}
}
return dp[i][j];
}
public int countPaths(int[][] grid) {
this.m = grid.length;
this.n = grid[0].length;
this.grid = grid;
this.dp = new int[m][n];
for (int i = 0; i < m; ++i) {
Arrays.fill(dp[i], -1);
}
int result = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
result = (result + dfs(i, j)) % MOD;
}
}
return result;
}
}
Python
MOD = 10**9 + 7
class Solution:
def countPaths(self, grid):
m, n = len(grid), len(grid[0])
dp = [[-1] * n for _ in range(m)]
def dfs(i, j):
if dp[i][j] != -1:
return dp[i][j]
dp[i][j] = 1 # Each cell itself is a path
for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:
if 0 <= x < m and 0 <= y < n and grid[x][y] > grid[i][j]:
dp[i][j] = (dp[i][j] + dfs(x, y)) % MOD
return dp[i][j]
result = 0
for i in range(m):
for j in range(n):
result = (result + dfs(i, j)) % MOD
return result
Complexity
- ⏰ Time complexity:
O(m * n)
since each cell is processed once and its result is memoized. - 🧺 Space complexity:
O(m * n)
for the memoization table.