You are given a m x n
matrix grid
. Initially, you are located at the top-left corner (0, 0)
, and in each step, you can only move right or down in the matrix.
Among all possible paths starting from the top-left corner (0, 0)
and ending in the bottom-right corner (m - 1, n - 1)
, find the path with the maximum non-negative product. The product of a path is the product of all integers in the grid cells visited along the path.
Return the maximum non-negative product modulo 109 + 7
. If the maximum product is negative, return -1
.
Notice that the modulo is performed after getting the maximum product.
Example 1:
Input: grid = [[-1,-2,-3],[-2,-3,-3],[-3,-3,-2]] Output: -1 Explanation: It is not possible to get non-negative product in the path from (0, 0) to (2, 2), so return -1.
Example 2:
Input: grid = [[1,-2,1],[1,-2,1],[3,-4,1]] Output: 8 Explanation: Maximum non-negative product is shown (1 * 1 * -2 * -4 * 1 = 8).
Example 3:
Input: grid = [[1,3],[0,-4]] Output: 0 Explanation: Maximum non-negative product is shown (1 * 0 * -4 = 0).
Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 15
-4 <= grid[i][j] <= 4
This problem asks to find the maximum non-negative product along any path from the top-left to the bottom-right corner of a given matrix, moving only right or down. The solution utilizes dynamic programming to efficiently compute this maximum product.
Approach:
The core idea is to maintain two values at each cell (i, j) of the matrix:
min_prod(i, j)
: The minimum product among all paths reaching cell (i, j).max_prod(i, j)
: The maximum product among all paths reaching cell (i, j).We iterate through the matrix, calculating min_prod(i, j)
and max_prod(i, j)
based on the values from the cells above and to the left:
If grid[i][j] >= 0
:
max_prod(i, j) = max(max_prod(i-1, j), max_prod(i, j-1)) * grid[i][j]
min_prod(i, j) = min(min_prod(i-1, j), min_prod(i, j-1)) * grid[i][j]
If grid[i][j] < 0
:
max_prod(i, j) = min(min_prod(i-1, j), min_prod(i, j-1)) * grid[i][j]
(because multiplying by a negative number reverses the order)min_prod(i, j) = max(max_prod(i-1, j), max_prod(i, j-1)) * grid[i][j]
The base cases are the top-left cell (grid[0][0]
), where both min_prod
and max_prod
are initialized to grid[0][0]
. The first row and column are handled separately, as they only have one neighbor.
Finally, max_prod(m-1, n-1)
(the bottom-right cell) holds the maximum non-negative product. If it's negative, we return -1; otherwise, we return the result modulo 109 + 7.
Time Complexity: O(m*n), where 'm' and 'n' are the dimensions of the matrix. We iterate through each cell once.
Space Complexity: O(m*n) due to the dp
array which stores minimum and maximum product for each cell. We could optimize this to O(n) if we used only two rows (or columns) of the dp
array.
The provided code implements the described dynamic programming approach. The different language versions demonstrate the same algorithm with minor syntactic variations. Note the use of long long
or similar types in C++ and Java to handle potentially large intermediate products to prevent integer overflow. Python's arbitrary-precision integers handle this implicitly.
(Python3, Java, C++, Go code are included in the original response)
Optimization for Space Complexity (Illustrative Example in Python):
This optimization reduces the space complexity from O(m*n) to O(n) by only storing the previous row's data.
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
mod = 10**9 + 7
prev_row = [[grid[0][0]] * 2] # Initialize with the first row.
for i in range(1, m):
current_row = [[0]*2 for _ in range(n)]
for j in range(n):
v = grid[i][j]
if j == 0:
if v >=0:
current_row[j][0] = prev_row[0][0] * v
current_row[j][1] = prev_row[0][1] * v
else:
current_row[j][0] = prev_row[0][1] * v
current_row[j][1] = prev_row[0][0] * v
else:
if v >= 0:
current_row[j][0] = min(prev_row[j][0], current_row[j-1][0]) * v
current_row[j][1] = max(prev_row[j][1], current_row[j-1][1]) * v
else:
current_row[j][0] = max(prev_row[j][1], current_row[j-1][1]) * v
current_row[j][1] = min(prev_row[j][0], current_row[j-1][0]) * v
prev_row = current_row
ans = prev_row[-1][1]
return -1 if ans < 0 else ans % mod