Skip to content

Commit 49bbc43

Browse files
authored
feat: add solutions to lc problem: No.0311 (doocs#1626)
No.0311.Sparse Matrix Multiplication
1 parent 6112294 commit 49bbc43

File tree

7 files changed

+514
-187
lines changed

7 files changed

+514
-187
lines changed

solution/0300-0399/0311.Sparse Matrix Multiplication/README.md

Lines changed: 201 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -42,43 +42,58 @@
4242

4343
<!-- 这里可写通用的实现逻辑 -->
4444

45+
**方法一:直接相乘**
46+
47+
我们可以直接按照矩阵乘法的定义,计算出结果矩阵中的每一个元素。
48+
49+
时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。
50+
51+
**方法二:预处理**
52+
53+
我们可以预处理出两个矩阵的稀疏表示,即 $g1[i]$ 表示矩阵 $mat1$ 第 $i$ 行中所有非零元素的列下标和值,而 $g2[i]$ 表示矩阵 $mat2$ 第 $i$ 行中所有非零元素的列下标和值。
54+
55+
接下来,我们遍历每一行 $i$,遍历 $g1[i]$ 中的每一个元素 $(k, x)$,遍历 $g2[k]$ 中的每一个元素 $(j, y)$,那么最终 $mat1[i][k] \times mat2[k][j]$ 就会对应到结果矩阵中的 $ans[i][j]$,我们将所有的结果累加即可。
56+
57+
时间复杂度 $O(m \times n \times k)$,空间复杂度 $O(m \times n)$。
58+
4559
<!-- tabs:start -->
4660

4761
### **Python3**
4862

4963
<!-- 这里可写当前语言的特殊实现逻辑 -->
5064

51-
直接模拟。
52-
5365
```python
5466
class Solution:
5567
def multiply(self, mat1: List[List[int]], mat2: List[List[int]]) -> List[List[int]]:
56-
r1, c1, c2 = len(mat1), len(mat1[0]), len(mat2[0])
57-
res = [[0] * c2 for _ in range(r1)]
58-
for i in range(r1):
59-
for j in range(c2):
60-
for k in range(c1):
61-
res[i][j] += mat1[i][k] * mat2[k][j]
62-
return res
68+
m, n = len(mat1), len(mat2[0])
69+
ans = [[0] * n for _ in range(m)]
70+
for i in range(m):
71+
for j in range(n):
72+
for k in range(len(mat2)):
73+
ans[i][j] += mat1[i][k] * mat2[k][j]
74+
return ans
6375
```
6476

65-
用哈希表记录稀疏矩阵 mat1 中的非 0 值。
66-
6777
```python
6878
class Solution:
6979
def multiply(self, mat1: List[List[int]], mat2: List[List[int]]) -> List[List[int]]:
70-
r1, c1, c2 = len(mat1), len(mat1[0]), len(mat2[0])
71-
res = [[0] * c2 for _ in range(r1)]
72-
mp = defaultdict(list)
73-
for i in range(r1):
74-
for j in range(c1):
75-
if mat1[i][j] != 0:
76-
mp[i].append(j)
77-
for i in range(r1):
78-
for j in range(c2):
79-
for k in mp[i]:
80-
res[i][j] += mat1[i][k] * mat2[k][j]
81-
return res
80+
def f(mat: List[List[int]]) -> List[List[int]]:
81+
g = [[] for _ in range(len(mat))]
82+
for i, row in enumerate(mat):
83+
for j, x in enumerate(row):
84+
if x:
85+
g[i].append((j, x))
86+
return g
87+
88+
g1 = f(mat1)
89+
g2 = f(mat2)
90+
m, n = len(mat1), len(mat2[0])
91+
ans = [[0] * n for _ in range(m)]
92+
for i in range(m):
93+
for k, x in g1[i]:
94+
for j, y in g2[k]:
95+
ans[i][j] += x * y
96+
return ans
8297
```
8398

8499
### **Java**
@@ -88,26 +103,51 @@ class Solution:
88103
```java
89104
class Solution {
90105
public int[][] multiply(int[][] mat1, int[][] mat2) {
91-
int r1 = mat1.length, c1 = mat1[0].length, c2 = mat2[0].length;
92-
int[][] res = new int[r1][c2];
93-
Map<Integer, List<Integer>> mp = new HashMap<>();
94-
for (int i = 0; i < r1; ++i) {
95-
for (int j = 0; j < c1; ++j) {
96-
if (mat1[i][j] != 0) {
97-
mp.computeIfAbsent(i, k -> new ArrayList<>()).add(j);
106+
int m = mat1.length, n = mat2[0].length;
107+
int[][] ans = new int[m][n];
108+
for (int i = 0; i < m; ++i) {
109+
for (int j = 0; j < n; ++j) {
110+
for (int k = 0; k < mat2.length; ++k) {
111+
ans[i][j] += mat1[i][k] * mat2[k][j];
98112
}
99113
}
100114
}
101-
for (int i = 0; i < r1; ++i) {
102-
for (int j = 0; j < c2; ++j) {
103-
if (mp.containsKey(i)) {
104-
for (int k : mp.get(i)) {
105-
res[i][j] += mat1[i][k] * mat2[k][j];
106-
}
115+
return ans;
116+
}
117+
}
118+
```
119+
120+
```java
121+
class Solution {
122+
public int[][] multiply(int[][] mat1, int[][] mat2) {
123+
int m = mat1.length, n = mat2[0].length;
124+
int[][] ans = new int[m][n];
125+
var g1 = f(mat1);
126+
var g2 = f(mat2);
127+
for (int i = 0; i < m; ++i) {
128+
for (int[] p : g1[i]) {
129+
int k = p[0], x = p[1];
130+
for (int[] q : g2[k]) {
131+
int j = q[0], y = q[1];
132+
ans[i][j] += x * y;
107133
}
108134
}
109135
}
110-
return res;
136+
return ans;
137+
}
138+
139+
private List<int[]>[] f(int[][] mat) {
140+
int m = mat.length, n = mat[0].length;
141+
List<int[]>[] g = new List[m];
142+
Arrays.setAll(g, i -> new ArrayList<>());
143+
for (int i = 0; i < m; ++i) {
144+
for (int j = 0; j < n; ++j) {
145+
if (mat[i][j] != 0) {
146+
g[i].add(new int[] {j, mat[i][j]});
147+
}
148+
}
149+
}
150+
return g;
111151
}
112152
}
113153
```
@@ -118,20 +158,48 @@ class Solution {
118158
class Solution {
119159
public:
120160
vector<vector<int>> multiply(vector<vector<int>>& mat1, vector<vector<int>>& mat2) {
121-
int r1 = mat1.size(), c1 = mat1[0].size(), c2 = mat2[0].size();
122-
vector<vector<int>> res(r1, vector<int>(c2));
123-
unordered_map<int, vector<int>> mp;
124-
for (int i = 0; i < r1; ++i) {
125-
for (int j = 0; j < c1; ++j) {
126-
if (mat1[i][j] != 0) mp[i].push_back(j);
161+
int m = mat1.size(), n = mat2[0].size();
162+
vector<vector<int>> ans(m, vector<int>(n));
163+
for (int i = 0; i < m; ++i) {
164+
for (int j = 0; j < n; ++j) {
165+
for (int k = 0; k < mat2.size(); ++k) {
166+
ans[i][j] += mat1[i][k] * mat2[k][j];
167+
}
127168
}
128169
}
129-
for (int i = 0; i < r1; ++i) {
130-
for (int j = 0; j < c2; ++j) {
131-
for (int k : mp[i]) res[i][j] += mat1[i][k] * mat2[k][j];
170+
return ans;
171+
}
172+
};
173+
```
174+
175+
```cpp
176+
class Solution {
177+
public:
178+
vector<vector<int>> multiply(vector<vector<int>>& mat1, vector<vector<int>>& mat2) {
179+
int m = mat1.size(), n = mat2[0].size();
180+
vector<vector<int>> ans(m, vector<int>(n));
181+
auto g1 = f(mat1), g2 = f(mat2);
182+
for (int i = 0; i < m; ++i) {
183+
for (auto& [k, x] : g1[i]) {
184+
for (auto& [j, y] : g2[k]) {
185+
ans[i][j] += x * y;
186+
}
132187
}
133188
}
134-
return res;
189+
return ans;
190+
}
191+
192+
vector<vector<pair<int, int>>> f(vector<vector<int>>& mat) {
193+
int m = mat.size(), n = mat[0].size();
194+
vector<vector<pair<int, int>>> g(m);
195+
for (int i = 0; i < m; ++i) {
196+
for (int j = 0; j < n; ++j) {
197+
if (mat[i][j]) {
198+
g[i].emplace_back(j, mat[i][j]);
199+
}
200+
}
201+
}
202+
return g;
135203
}
136204
};
137205
```
@@ -140,27 +208,99 @@ public:
140208

141209
```go
142210
func multiply(mat1 [][]int, mat2 [][]int) [][]int {
143-
r1, c1, c2 := len(mat1), len(mat1[0]), len(mat2[0])
144-
res := make([][]int, r1)
145-
for i := range res {
146-
res[i] = make([]int, c2)
211+
m, n := len(mat1), len(mat2[0])
212+
ans := make([][]int, m)
213+
for i := range ans {
214+
ans[i] = make([]int, n)
147215
}
148-
mp := make(map[int][]int)
149-
for i := 0; i < r1; i++ {
150-
for j := 0; j < c1; j++ {
151-
if mat1[i][j] != 0 {
152-
mp[i] = append(mp[i], j)
216+
for i := 0; i < m; i++ {
217+
for j := 0; j < n; j++ {
218+
for k := 0; k < len(mat2); k++ {
219+
ans[i][j] += mat1[i][k] * mat2[k][j]
153220
}
154221
}
155222
}
156-
for i := 0; i < r1; i++ {
157-
for j := 0; j < c2; j++ {
158-
for _, k := range mp[i] {
159-
res[i][j] += mat1[i][k] * mat2[k][j]
223+
return ans
224+
}
225+
```
226+
227+
```go
228+
func multiply(mat1 [][]int, mat2 [][]int) [][]int {
229+
m, n := len(mat1), len(mat2[0])
230+
ans := make([][]int, m)
231+
for i := range ans {
232+
ans[i] = make([]int, n)
233+
}
234+
f := func(mat [][]int) [][][2]int {
235+
m, n := len(mat), len(mat[0])
236+
g := make([][][2]int, m)
237+
for i := range g {
238+
g[i] = make([][2]int, 0, n)
239+
for j := range mat[i] {
240+
if mat[i][j] != 0 {
241+
g[i] = append(g[i], [2]int{j, mat[i][j]})
242+
}
160243
}
161244
}
245+
return g
162246
}
163-
return res
247+
g1, g2 := f(mat1), f(mat2)
248+
for i := range g1 {
249+
for _, p := range g1[i] {
250+
k, x := p[0], p[1]
251+
for _, q := range g2[k] {
252+
j, y := q[0], q[1]
253+
ans[i][j] += x * y
254+
}
255+
}
256+
}
257+
return ans
258+
}
259+
```
260+
261+
### **TypeScript**
262+
263+
```ts
264+
function multiply(mat1: number[][], mat2: number[][]): number[][] {
265+
const [m, n] = [mat1.length, mat2[0].length];
266+
const ans: number[][] = Array.from({ length: m }, () => Array.from({ length: n }, () => 0));
267+
for (let i = 0; i < m; ++i) {
268+
for (let j = 0; j < n; ++j) {
269+
for (let k = 0; k < mat2.length; ++k) {
270+
ans[i][j] += mat1[i][k] * mat2[k][j];
271+
}
272+
}
273+
}
274+
return ans;
275+
}
276+
```
277+
278+
```ts
279+
function multiply(mat1: number[][], mat2: number[][]): number[][] {
280+
const [m, n] = [mat1.length, mat2[0].length];
281+
const ans: number[][] = Array.from({ length: m }, () => Array.from({ length: n }, () => 0));
282+
const f = (mat: number[][]): number[][][] => {
283+
const [m, n] = [mat.length, mat[0].length];
284+
const ans: number[][][] = Array.from({ length: m }, () => []);
285+
for (let i = 0; i < m; ++i) {
286+
for (let j = 0; j < n; ++j) {
287+
if (mat[i][j] !== 0) {
288+
ans[i].push([j, mat[i][j]]);
289+
}
290+
}
291+
}
292+
return ans;
293+
};
294+
const g1 = f(mat1);
295+
const g2 = f(mat2);
296+
for (let i = 0; i < m; ++i) {
297+
for (const [k, x] of g1[i]) {
298+
for (const [j, y] of g2[k]) {
299+
ans[i][j] += x * y;
300+
}
301+
}
302+
}
303+
return ans;
164304
}
165305
```
166306

0 commit comments

Comments
 (0)