1594. 矩阵的最大非负积
大约 4 分钟
--- 

1594. 矩阵的最大非负积
- 标签:数组、动态规划
- 难度:中等
题目链接
题目大意
描述:给定一个 的整数矩阵 。从左上角 出发,每次只能向右或向下移动,到达右下角 。路径上所有数字的乘积即为路径的得分。
要求:返回最大非负得分(如果最大得分为负数,返回 )。结果对 取模。
说明:
- 。
- 。
示例:
- 示例 1:

输入:grid = [[-1,-2,-3],[-2,-3,-3],[-3,-3,-2]]
输出:-1
解释:从 (0, 0) 到 (2, 2) 的路径中无法得到非负积,所以返回 -1 。- 示例 2:

输入:grid = [[1,-2,1],[1,-2,1],[3,-4,1]]
输出:8
解释:最大非负积对应的路径如图所示 (1 * 1 * -2 * -4 * 1 = 8)解题思路
思路 1:二维 DP(维护最大和最小值)
1. 核心思想
由于有负数存在,最小负数乘以负数可能变成最大正数。因此每个位置需要同时维护最大值和最小值。
定义 为从 到 的最大积, 为最小积。
2. 具体步骤
第 1 步:初始化 。
第 2 步:初始化第一行和第一列。
第 3 步:遍历 ,:
- 从上方 和左方 转移。
- 当前值 。
- 如果 :
- 如果 :
- 如果 :
- 。
第 4 步:返回 。如果为负数,返回 。
3. 举例说明
以 为例:
j=0 j=1 j=2
i=0 1 -2 1
i=1 1 -2 1
i=2 3 -4 1初始化 :。
第一行 / 第一列(只有单一前驱,按符号规则转移即可):
| 位置 | 前驱 | |||
|---|---|---|---|---|
| 左 | ||||
| 左 | ||||
| 上 | ||||
| 上 |
内部格子(需同时比较上方和左方前驱):
- ,:上 为 ,左 为 。
- ,:上 为 ,左 为 。
- ,:上 为 ,左 为 。
- (负负得正,取前驱最小值)
- ,:上 为 ,左 为 。
最终 与 如下(括号内为 ):
j=0 j=1 j=2
i=0 (1, 1) (-2,-2) (-2,-2)
i=1 (1, 1) (4, -2) (4, -2)
i=2 (3, 3) (8,-16) (8,-16)终点 ,返回 。
对应最优路径:,路径积 。
思路 1:代码
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
MOD = 10 ** 9 + 7
m, n = len(grid), len(grid[0])
max_dp = [[0] * n for _ in range(m)]
min_dp = [[0] * n for _ in range(m)]
max_dp[0][0] = min_dp[0][0] = grid[0][0]
# 初始化第一行
for j in range(1, n):
v = grid[0][j]
if v >= 0:
max_dp[0][j] = max_dp[0][j-1] * v
min_dp[0][j] = min_dp[0][j-1] * v
else:
max_dp[0][j] = min_dp[0][j-1] * v
min_dp[0][j] = max_dp[0][j-1] * v
# 初始化第一列
for i in range(1, m):
v = grid[i][0]
if v >= 0:
max_dp[i][0] = max_dp[i-1][0] * v
min_dp[i][0] = min_dp[i-1][0] * v
else:
max_dp[i][0] = min_dp[i-1][0] * v
min_dp[i][0] = max_dp[i-1][0] * v
for i in range(1, m):
for j in range(1, n):
v = grid[i][j]
if v >= 0:
max_dp[i][j] = max(max_dp[i-1][j], max_dp[i][j-1]) * v
min_dp[i][j] = min(min_dp[i-1][j], min_dp[i][j-1]) * v
else:
max_dp[i][j] = min(min_dp[i-1][j], min_dp[i][j-1]) * v
min_dp[i][j] = max(max_dp[i-1][j], max_dp[i][j-1]) * v
ans = max_dp[m-1][n-1]
return -1 if ans < 0 else ans % MOD思路 1:复杂度分析
- 时间复杂度:。
- 空间复杂度:,可优化为 。