
Input: matrix =[[1,2],[3,4]]Output: [[1,2],[2,3]]Explanation:
The rank of matrix[0][0]is1 because it is the smallest integer in its row and column.The rank of matrix[0][1]is2 because matrix[0][1]> matrix[0][0] and matrix[0][0]is rank 1.The rank of matrix[1][0]is2 because matrix[1][0]> matrix[0][0] and matrix[0][0]is rank 1.The rank of matrix[1][1]is3 because matrix[1][1]> matrix[0][1], matrix[1][1]> matrix[1][0], and both matrix[0][1] and matrix[1][0] are rank 2.
The key idea is to process matrix values in increasing order, grouping equal values in the same row or column using union-find. This ensures that all constraints are satisfied and ranks are assigned minimally.
classSolution {
publicint[][]matrixRankTransform(int[][] mat) {
int m = mat.length, n = mat[0].length;
Map<Integer, List<int[]>> val2pos =new TreeMap<>();
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
val2pos.computeIfAbsent(mat[i][j], k ->new ArrayList<>()).add(newint[]{i, j});
int[] row =newint[m], col =newint[n];
int[][] ans =newint[m][n];
for (int val : val2pos.keySet()) {
List<int[]> pos = val2pos.get(val);
int[] p =newint[m + n];
for (int i = 0; i < m + n; ++i) p[i]= i;
Function<Integer, Integer> find =new Function<>() {
public Integer apply(Integer x) {
if (p[x]!= x) p[x]=this.apply(p[x]);
return p[x];
}
};
for (int[] v : pos) p[find.apply(v[0])]= find.apply(v[1]+ m);
Map<Integer, Integer> groupMax =new HashMap<>();
for (int[] v : pos) {
int g = find.apply(v[0]);
groupMax.put(g, Math.max(groupMax.getOrDefault(g, 0), Math.max(row[v[0]], col[v[1]])));
}
for (int[] v : pos) {
int g = find.apply(v[0]);
ans[v[0]][v[1]]= groupMax.get(g) + 1;
}
for (int[] v : pos) {
row[v[0]]= ans[v[0]][v[1]];
col[v[1]]= ans[v[0]][v[1]];
}
}
return ans;
}
}
classSolution {
funmatrixRankTransform(mat: Array<IntArray>): Array<IntArray> {
val m = mat.size
val n = mat[0].size
val val2pos = sortedMapOf<Int, MutableList<Pair<Int, Int>>>()
for (i in0 until m)
for (j in0 until n)
val2pos.getOrPut(mat[i][j]) { mutableListOf() }.add(i to j)
val row = IntArray(m)
val col = IntArray(n)
val ans = Array(m) { IntArray(n) }
for ((_, pos) in val2pos) {
val p = IntArray(m + n) { it }
funfind(x: Int): Int = if (p[x] == x) x else { p[x] = find(p[x]); p[x] }
for ((i, j) in pos) p[find(i)] = find(j + m)
val groupMax = mutableMapOf<Int, Int>()
for ((i, j) in pos) {
val g = find(i)
groupMax[g] = maxOf(groupMax.getOrDefault(g, 0), row[i], col[j])
}
for ((i, j) in pos) {
val g = find(i)
ans[i][j] = groupMax[g]!! + 1 }
for ((i, j) in pos) {
row[i] = ans[i][j]
col[j] = ans[i][j]
}
}
return ans
}
}
from typing import List
classSolution:
defmatrixRankTransform(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
from collections import defaultdict
val2pos = defaultdict(list)
for i in range(m):
for j in range(n):
val2pos[mat[i][j]].append((i, j))
row = [0] * m
col = [0] * n
ans = [[0] * n for _ in range(m)]
for val in sorted(val2pos):
p = list(range(m + n))
deffind(x):
if p[x] != x:
p[x] = find(p[x])
return p[x]
for i, j in val2pos[val]:
p[find(i)] = find(j + m)
groupMax = dict()
for i, j in val2pos[val]:
g = find(i)
groupMax[g] = max(groupMax.get(g, 0), row[i], col[j])
for i, j in val2pos[val]:
g = find(i)
ans[i][j] = groupMax[g] +1for i, j in val2pos[val]:
row[i] = ans[i][j]
col[j] = ans[i][j]
return ans
⏰ Time complexity: O((m * n) * α(m + n)), where α is the inverse Ackermann function, due to union-find operations for each unique value and all positions. Sorting values and iterating over all cells is also O(m * n log(m * n)) in the worst case.
🧺 Space complexity: O(m * n), for storing mappings, union-find parent arrays, and the answer matrix.