@@ -82,23 +82,38 @@ matrix[1][1] 的秩为 3 ,因为 matrix[1][1] > matrix[0][1], matrix[1][1] >
82
82
83
83
这种联动容易想到并查集,于是用并查集将相同元素分为几个连通块,对于每个连通块,里面所有元素对应的行或列的最大秩加 $1$,即为该连通块内所有元素的秩。
84
84
85
+ 时间复杂度 $O(m \times n \times \log(m \times n))$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为矩阵的行数和列数。
86
+
85
87
<!-- tabs:start -->
86
88
87
89
### ** Python3**
88
90
89
91
<!-- 这里可写当前语言的特殊实现逻辑 -->
90
92
91
93
``` python
92
- class Solution :
93
- def matrixRankTransform (self , matrix : List[List[int ]]) -> List[List[int ]]:
94
- def find (x ):
95
- if p.setdefault(x, x) != x:
96
- p[x] = find(p[x])
97
- return p[x]
94
+ class UnionFind :
95
+ def __init__ (self , n ):
96
+ self .p = list (range (n))
97
+ self .size = [1 ] * n
98
+
99
+ def find (self , x ):
100
+ if self .p[x] != x:
101
+ self .p[x] = self .find(self .p[x])
102
+ return self .p[x]
103
+
104
+ def union (self , a , b ):
105
+ pa, pb = self .find(a), self .find(b)
106
+ if pa != pb:
107
+ if self .size[pa] > self .size[pb]:
108
+ self .p[pb] = pa
109
+ self .size[pa] += self .size[pb]
110
+ else :
111
+ self .p[pa] = pb
112
+ self .size[pb] += self .size[pa]
98
113
99
- def union (a , b ):
100
- p[find(a)] = find(b)
101
114
115
+ class Solution :
116
+ def matrixRankTransform (self , matrix : List[List[int ]]) -> List[List[int ]]:
102
117
m, n = len (matrix), len (matrix[0 ])
103
118
d = defaultdict(list )
104
119
for i, row in enumerate (matrix):
@@ -108,13 +123,14 @@ class Solution:
108
123
col_max = [0 ] * n
109
124
ans = [[0 ] * n for _ in range (m)]
110
125
for v in sorted (d):
111
- p, rank = {}, defaultdict(int )
126
+ uf = UnionFind(m + n)
127
+ rank = defaultdict(int )
112
128
for i, j in d[v]:
113
- union(i, j + 500 )
129
+ uf. union(i, j + m )
114
130
for i, j in d[v]:
115
- rank[find(i)] = max (rank[find(i)], row_max[i], col_max[j])
131
+ rank[uf. find(i)] = max (rank[uf. find(i)], row_max[i], col_max[j])
116
132
for i, j in d[v]:
117
- ans[i][j] = row_max[i] = col_max[j] = 1 + rank[find(i)]
133
+ ans[i][j] = row_max[i] = col_max[j] = 1 + rank[uf. find(i)]
118
134
return ans
119
135
```
120
136
@@ -123,10 +139,42 @@ class Solution:
123
139
<!-- 这里可写当前语言的特殊实现逻辑 -->
124
140
125
141
``` java
126
- class Solution {
127
- private Map<Integer , Integer > p = new HashMap<> ();
128
- private Map<Integer , Integer > rank = new HashMap<> ();
142
+ class UnionFind {
143
+ private int [] p;
144
+ private int [] size;
145
+
146
+ public UnionFind (int n ) {
147
+ p = new int [n];
148
+ size = new int [n];
149
+ for (int i = 0 ; i < n; ++ i) {
150
+ p[i] = i;
151
+ size[i] = 1 ;
152
+ }
153
+ }
154
+
155
+ public int find (int x ) {
156
+ if (p[x] != x) {
157
+ p[x] = find(p[x]);
158
+ }
159
+ return p[x];
160
+ }
161
+
162
+ public void union (int a , int b ) {
163
+ int pa = find(a), pb = find(b);
164
+ if (pa != pb) {
165
+ if (size[pa] > size[pb]) {
166
+ p[pb] = pa;
167
+ size[pa] += size[pb];
168
+ } else {
169
+ p[pa] = pb;
170
+ size[pb] += size[pa];
171
+ }
172
+ }
173
+ }
174
+ }
129
175
176
+
177
+ class Solution {
130
178
public int [][] matrixRankTransform (int [][] matrix ) {
131
179
int m = matrix. length, n = matrix[0 ]. length;
132
180
TreeMap<Integer , List<int[]> > d = new TreeMap<> ();
@@ -138,46 +186,63 @@ class Solution {
138
186
int [] rowMax = new int [m];
139
187
int [] colMax = new int [n];
140
188
int [][] ans = new int [m][n];
141
- for (var e : d. entrySet()) {
142
- int v = e. getKey();
143
- var g = e. getValue();
144
- p. clear();
145
- rank. clear();
146
- for (int [] x : g) {
147
- union(x[0 ], x[1 ] + 500 );
189
+ for (var ps : d. values()) {
190
+ UnionFind uf = new UnionFind (m + n);
191
+ int [] rank = new int [m + n];
192
+ for (var p : ps) {
193
+ uf. union(p[0 ], p[1 ] + m);
148
194
}
149
- for (int [] x : g) {
150
- int i = x[0 ], j = x[1 ];
151
- rank. put(find(i),
152
- Math . max(rank. getOrDefault(find(i), 0 ), Math . max(rowMax[i], colMax[j])));
195
+ for (var p : ps) {
196
+ int i = p[0 ], j = p[1 ];
197
+ rank[uf. find(i)] = Math . max(rank[uf. find(i)], Math . max(rowMax[i], colMax[j]));
153
198
}
154
- for (int [] x : g ) {
155
- int i = x [0 ], j = x [1 ];
156
- ans[i][j] = 1 + rank. getOrDefault( find(i), 0 ) ;
199
+ for (var p : ps ) {
200
+ int i = p [0 ], j = p [1 ];
201
+ ans[i][j] = 1 + rank[uf . find(i)] ;
157
202
rowMax[i] = ans[i][j];
158
203
colMax[j] = ans[i][j];
159
204
}
160
205
}
161
206
return ans;
162
207
}
208
+ }
209
+ ```
210
+
211
+ ### ** C++**
212
+
213
+ ``` cpp
214
+ class UnionFind {
215
+ public:
216
+ UnionFind(int n) {
217
+ p = vector<int >(n);
218
+ size = vector<int >(n, 1);
219
+ iota(p.begin(), p.end(), 0);
220
+ }
163
221
164
- private void union (int a , int b ) {
165
- p. put(find(a), find(b));
222
+ void unite(int a, int b) {
223
+ int pa = find(a), pb = find(b);
224
+ if (pa != pb) {
225
+ if (size[pa] > size[pb]) {
226
+ p[pb] = pa;
227
+ size[pa] += size[pb];
228
+ } else {
229
+ p[pa] = pb;
230
+ size[pb] += size[pa];
231
+ }
232
+ }
166
233
}
167
234
168
- private int find (int x ) {
169
- p. putIfAbsent(x, x);
170
- if (p. get(x) != x) {
171
- p. put(x, find(p. get(x)));
235
+ int find (int x) {
236
+ if (p[ x] != x) {
237
+ p[ x] = find(p[ x] );
172
238
}
173
- return p. get(x) ;
239
+ return p[ x ] ;
174
240
}
175
- }
176
- ```
177
241
178
- ### ** C++**
242
+ private:
243
+ vector<int > p, size;
244
+ };
179
245
180
- ``` cpp
181
246
class Solution {
182
247
public:
183
248
vector<vector<int >> matrixRankTransform(vector<vector<int >>& matrix) {
@@ -191,32 +256,107 @@ public:
191
256
vector<int > rowMax(m);
192
257
vector<int > colMax(n);
193
258
vector<vector<int >> ans(m, vector<int >(n));
194
- for (auto& [ v, g ] : d) {
195
- unordered_map<int, int> p ;
196
- unordered_map <int, int > rank;
197
- for (auto [ i, j] : g ) {
198
- unite(i, j + 500, p );
259
+ for (auto& [ _ , ps ] : d) {
260
+ UnionFind uf(m + n) ;
261
+ vector <int > rank(m + n) ;
262
+ for (auto& [ i, j] : ps ) {
263
+ uf. unite(i, j + m );
199
264
}
200
- for (auto [ i, j] : g ) {
201
- rank[ find(i, p )] = max(rank[ find(i, p )] , max( rowMax[ i] , colMax[ j] ) );
265
+ for (auto& [ i, j] : ps ) {
266
+ rank[ uf. find(i)] = max({ rank[ uf. find(i)] , rowMax[ i] , colMax[ j] } );
202
267
}
203
- for (auto [ i, j] : g ) {
204
- ans[ i] [ j ] = rowMax[ i] = colMax[ j] = 1 + rank[ find(i, p )] ;
268
+ for (auto& [ i, j] : ps ) {
269
+ ans[ i] [ j ] = rowMax[ i] = colMax[ j] = 1 + rank[ uf. find(i)] ;
205
270
}
206
271
}
207
272
return ans;
208
273
}
274
+ };
275
+ ```
209
276
210
- void unite(int a, int b, unordered_map<int, int>& p) {
211
- p[find(a, p)] = find(b, p);
212
- }
277
+ ### **Go**
213
278
214
- int find (int x, unordered_map<int, int>& p) {
215
- if (!p.count(x)) p[ x] = x;
216
- if (p[ x] != x) p[ x] = find(p[ x] , p);
217
- return p[ x] ;
218
- }
219
- };
279
+ ```go
280
+ type unionFind struct {
281
+ p, size []int
282
+ }
283
+
284
+ func newUnionFind(n int) *unionFind {
285
+ p := make([]int, n)
286
+ size := make([]int, n)
287
+ for i := range p {
288
+ p[i] = i
289
+ size[i] = 1
290
+ }
291
+ return &unionFind{p, size}
292
+ }
293
+
294
+ func (uf *unionFind) find(x int) int {
295
+ if uf.p[x] != x {
296
+ uf.p[x] = uf.find(uf.p[x])
297
+ }
298
+ return uf.p[x]
299
+ }
300
+
301
+ func (uf *unionFind) union(a, b int) {
302
+ pa, pb := uf.find(a), uf.find(b)
303
+ if pa != pb {
304
+ if uf.size[pa] > uf.size[pb] {
305
+ uf.p[pb] = pa
306
+ uf.size[pa] += uf.size[pb]
307
+ } else {
308
+ uf.p[pa] = pb
309
+ uf.size[pb] += uf.size[pa]
310
+ }
311
+ }
312
+ }
313
+
314
+ func matrixRankTransform(matrix [][]int) [][]int {
315
+ m, n := len(matrix), len(matrix[0])
316
+ type pair struct{ i, j int }
317
+ d := map[int][]pair{}
318
+ for i, row := range matrix {
319
+ for j, v := range row {
320
+ d[v] = append(d[v], pair{i, j})
321
+ }
322
+ }
323
+ rowMax := make([]int, m)
324
+ colMax := make([]int, n)
325
+ ans := make([][]int, m)
326
+ for i := range ans {
327
+ ans[i] = make([]int, n)
328
+ }
329
+ vs := []int{}
330
+ for v := range d {
331
+ vs = append(vs, v)
332
+ }
333
+ sort.Ints(vs)
334
+ for _, v := range vs {
335
+ ps := d[v]
336
+ uf := newUnionFind(m + n)
337
+ rank := make([]int, m+n)
338
+ for _, p := range ps {
339
+ uf.union(p.i, p.j+m)
340
+ }
341
+ for _, p := range ps {
342
+ i, j := p.i, p.j
343
+ rank[uf.find(i)] = max(rank[uf.find(i)], max(rowMax[i], colMax[j]))
344
+ }
345
+ for _, p := range ps {
346
+ i, j := p.i, p.j
347
+ ans[i][j] = 1 + rank[uf.find(i)]
348
+ rowMax[i], colMax[j] = ans[i][j], ans[i][j]
349
+ }
350
+ }
351
+ return ans
352
+ }
353
+
354
+ func max(a, b int) int {
355
+ if a > b {
356
+ return a
357
+ }
358
+ return b
359
+ }
220
360
```
221
361
222
362
### ** ...**
0 commit comments