本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。
为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。
由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。
给你一个下标从 0 开始、大小为 n * m 的二维整数矩阵 grid ,定义一个下标从 0 开始、大小为 n * m 的的二维矩阵 p。如果满足以下条件,则称 p 为 grid 的 乘积矩阵 :
p[i][j] ,它的值等于除了 grid[i][j] 外所有元素的乘积。乘积对 12345 取余数。返回 grid 的乘积矩阵。
示例 1:
输入:grid = [[1,2],[3,4]]
输出:[[24,12],[8,6]]
解释:p[0][0] = grid[0][1] * grid[1][0] * grid[1][1] = 2 * 3 * 4 = 24
p[0][1] = grid[0][0] * grid[1][0] * grid[1][1] = 1 * 3 * 4 = 12
p[1][0] = grid[0][0] * grid[0][1] * grid[1][1] = 1 * 2 * 4 = 8
p[1][1] = grid[0][0] * grid[0][1] * grid[1][0] = 1 * 2 * 3 = 6
所以答案是 [[24,12],[8,6]] 。
示例 2:
输入:grid = [[12345],[2],[1]]
输出:[[2],[0],[0]]
解释:p[0][0] = grid[0][1] * grid[0][2] = 2 * 1 = 2
p[0][1] = grid[0][0] * grid[0][2] = 12345 * 1 = 12345. 12345 % 12345 = 0 ,所以 p[0][1] = 0
p[0][2] = grid[0][0] * grid[0][1] = 12345 * 2 = 24690. 24690 % 12345 = 0 ,所以 p[0][2] = 0
所以答案是 [[2],[0],[0]] 。
提示:
1 <= n == grid.length <= 10^51 <= m == grid[i].length <= 10^52 <= n * m <= 10^51 <= grid[i][j] <= 10^9前后缀分解(右边的数字为难度分)
核心思想:把矩阵拉成一维的,我们需要算出每个数左边所有数的乘积,以及右边所有数的乘积,这都可以用递推得到。
先算出从 g r i d [ i ] [ j ] grid[i][j] grid[i][j] 的下一个元素开始,到最后一个元素 g r i d [ n − 1 ] [ m − 1 ] grid[n−1][m−1] grid[n−1][m−1] 的乘积,记作 s u f [ i ] [ j ] suf[i][j] suf[i][j] 。这可以从最后一行最后一列开始,倒着遍历得到。
然后算出从第一个元素 g r i d [ 0 ] [ 0 ] grid[0][0] grid[0][0] 开始,到 g r i d [ i ] [ j ] grid[i][j] grid[i][j] 的上一个元素的乘积,记作 p r e [ i ] [ j ] pre[i][j] pre[i][j] 。这可以从第一行第一列开始,正着遍历得到。
那么:
p
[
i
]
[
j
]
=
p
r
e
[
i
]
[
j
]
⋅
s
u
f
[
i
]
[
j
]
p[i][j]=pre[i][j]⋅suf[i][j]
p[i][j]=pre[i][j]⋅suf[i][j]
代码实现时,可以先初始化
p
[
i
]
[
j
]
=
s
u
f
[
i
]
[
j
]
p[i][j]=suf[i][j]
p[i][j]=suf[i][j] ,然后把
p
r
e
[
i
]
[
j
]
pre[i][j]
pre[i][j] 乘到
p
[
i
]
[
j
]
p[i][j]
p[i][j] 中,就得到了答案。这样
p
r
e
pre
pre 和
s
u
f
suf
suf 就可以压缩成一个变量。
class Solution {
public:
vector<vector<int>> constructProductMatrix(vector<vector<int>>& grid) {
const int MOD = 12345;
int n = grid.size(), m = grid[0].size();
vector<vector<int>> p(n, vector<int>(m));
long long suf = 1; // 后缀乘积
for (int i = n - 1; i >= 0; --i) {
for (int j = m - 1; j >= 0; --j) {
p[i][j] = suf; // p[i][j]先初始化为后缀乘积
suf = suf * grid[i][j] % MOD;
}
}
long long pre = 1; // 前缀乘积
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
p[i][j] = p[i][j] * pre % MOD; // 然后再乘上前缀乘积
pre = pre * grid[i][j] % MOD;
}
}
return p;
}
};