思路:
整体思路是将矩阵中每个元素当作一个点,根据大小关系构造有向图之后进行拓扑排序。由于题目要求每一行(列)中相等的元素的秩要相等,所以在建图的时候考虑把这样的元素对应的点合并成一个点。具体实现使用并查集或者强连通分量缩点都可以。
实现1(并查集):
1 class Solution 2 { 3 public: 4 int find(int x, vector<int>& p) 5 { 6 if (x == p[x]) return x; 7 return p[x] = find(p[x], p); 8 } 9 void uni(int x, int y, vector<int>& p) 10 { 11 x = find(x, p); y = find(y, p); 12 if (x != y) p[x] = y; 13 } 14 vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) 15 { 16 int n = matrix.size(), m = matrix[0].size(); 17 vector<vector<int>> res(n, vector<int>(m, 0)); 18 vector<int> p(n * m); 19 for (int i = 0; i < n * m; i++) p[i] = i; 20 vector<vector<int>> g(n * m, vector<int>()); 21 vector<pair<int, int>> add; 22 for (int i = 0; i < n; i++) 23 { 24 vector<pair<int, int>> v; 25 for (int j = 0; j < matrix[i].size(); j++) 26 { 27 v.push_back(make_pair(matrix[i][j], i * m + j)); 28 } 29 sort(v.begin(), v.end()); 30 for (int j = 0; j < v.size() - 1; j++) 31 { 32 int id = v[j].second, nid = v[j + 1].second; 33 if (v[j].first == v[j + 1].first) uni(id, nid, p); 34 else add.push_back(make_pair(id, nid)); 35 } 36 } 37 for (int j = 0; j < m; j++) 38 { 39 vector<pair<int, int>> v; 40 for (int i = 0; i < n; i++) 41 { 42 v.push_back(make_pair(matrix[i][j], i * m + j)); 43 } 44 sort(v.begin(), v.end()); 45 for (int i = 0; i < v.size() - 1; i++) 46 { 47 int id = v[i].second, nid = v[i + 1].second; 48 if (v[i].first == v[i + 1].first) uni(id, nid, p); 49 else add.push_back(make_pair(id, nid)); 50 } 51 } 52 for (auto it: add) 53 { 54 int s = it.first, t = it.second; 55 s = find(s, p); t = find(t, p); 56 g[s].push_back(t); 57 } 58 vector<int> ind(n * m, 0); 59 for (int i = 0; i < n * m; i++) 60 { 61 for (int j = 0; j < g[i].size(); j++) 62 { 63 ind[g[i][j]]++; 64 } 65 } 66 queue<pair<int, int>> q; 67 for (int i = 0; i < n * m; i++) 68 { 69 if (ind[i] == 0) q.push(make_pair(i, 1)); 70 } 71 vector<int> rank_p(n * m, 0); 72 while (!q.empty()) 73 { 74 pair<int, int> tmp = q.front(); q.pop(); 75 int id = tmp.first; 76 int x = id / m, y = id % m; 77 int r = tmp.second; 78 int pa = find(id, p); 79 rank_p[pa] = max(rank_p[pa], r); 80 for (int i = 0; i < g[id].size(); i++) 81 { 82 int e = g[id][i]; 83 ind[e]--; 84 if (ind[e] == 0) q.push(make_pair(e, r + 1)); 85 } 86 } 87 for (int i = 0; i < n; i++) 88 { 89 for (int j = 0; j < m; j++) 90 { 91 int id = i * m + j; 92 int pa = find(id, p); 93 res[i][j] = rank_p[pa]; 94 } 95 } 96 return res; 97 } 98 };
实现2(强连通分量缩点):
1 class Solution 2 { 3 public: 4 void add_edge(int x, int y, vector<vector<int>>& G, vector<vector<int>>& rG) 5 { 6 G[x].push_back(y); rG[y].push_back(x); 7 } 8 void dfs(int x, vector<vector<int>>& G, vector<int>& used, vector<int>& vs) 9 { 10 used[x] = 1; 11 for (int i = 0; i < G[x].size(); i++) 12 { 13 int t = G[x][i]; 14 if (!used[t]) dfs(t, G, used, vs); 15 } 16 vs.push_back(x); 17 } 18 void rdfs(int x, vector<vector<int>>& rG, vector<int>& used, vector<int>& cmp, int cmp_id) 19 { 20 used[x] = 1; 21 cmp[x] = cmp_id; 22 for (int i = 0; i < rG[x].size(); i++) 23 { 24 int t = rG[x][i]; 25 if (!used[t]) rdfs(t, rG, used, cmp, cmp_id); 26 } 27 } 28 void construct_graph(vector<pair<int, int>>& v, vector<vector<int>>& G, vector<vector<int>>& rG) 29 { 30 sort(v.begin(), v.end()); 31 int n = v.size(); 32 for (int i = 0; i < n; i++) 33 { 34 int j = i; 35 while (j < n and v[j].first == v[i].first) j++; 36 for (int k = i; k < min(j, n - 1); k++) 37 { 38 add_edge(v[k].second, v[k + 1].second, G, rG); 39 } 40 if (j - i >= 2) 41 { 42 add_edge(v[j - 1].second, v[i].second, G, rG); 43 } 44 i = j - 1; 45 } 46 } 47 pair<vector<vector<int>>, vector<int>> scc(vector<vector<int>>& matrix) 48 { 49 int n = matrix.size(), m = matrix[0].size(); 50 vector<vector<int>> G(n * m, vector<int>()), rG(n * m, vector<int>()); 51 for (int i = 0; i < n; i++) 52 { 53 vector<pair<int, int>> v; 54 for (int j = 0; j < m; j++) 55 { 56 v.push_back(make_pair(matrix[i][j], i * m + j)); 57 } 58 construct_graph(v, G, rG); 59 } 60 for (int j = 0; j < m; j++) 61 { 62 vector<pair<int, int>> v; 63 for (int i = 0; i < n; i++) 64 { 65 v.push_back(make_pair(matrix[i][j], i * m + j)); 66 } 67 construct_graph(v, G, rG); 68 } 69 vector<int> vs, used(n * m, 0); 70 for (int i = 0; i < n * m; i++) 71 { 72 if (!used[i]) dfs(i, G, used, vs); 73 } 74 fill(used.begin(), used.end(), 0); 75 vector<int> cmp(n * m, -1); 76 int cnt = 0; 77 for (int i = vs.size() - 1; i >= 0; i--) 78 { 79 if (!used[vs[i]]) rdfs(vs[i], rG, used, cmp, cnt++); 80 } 81 vector<vector<int>> g(cnt, vector<int>()); 82 for (int i = 0; i < n * m; i++) 83 { 84 int x = cmp[i]; 85 if (x == -1) continue; 86 for (int j = 0; j < G[i].size(); j++) 87 { 88 int t = G[i][j]; 89 int y = cmp[t]; 90 if (x == y) continue; 91 g[x].push_back(y); 92 } 93 } 94 return make_pair(g, cmp); 95 } 96 vector<int> toposort(vector<vector<int>>& g) 97 { 98 int n = g.size(); 99 vector<int> ind(n, 0); 100 for (int i = 0; i < n; i++) 101 { 102 for (int j = 0; j < g[i].size(); j++) 103 { 104 int t = g[i][j]; 105 ind[t]++; 106 } 107 } 108 queue<pair<int, int>> q; 109 for (int i = 0; i < n; i++) 110 { 111 if (ind[i] == 0) q.push(make_pair(i, 1)); 112 } 113 vector<int> rank(n, 0); 114 while (!q.empty()) 115 { 116 pair<int, int> tmp = q.front(); q.pop(); 117 int p = tmp.first, r = tmp.second; 118 rank[p] = max(rank[p], r); 119 for (int i = 0; i < g[p].size(); i++) 120 { 121 int e = g[p][i]; 122 ind[e]--; 123 if (ind[e] == 0) q.push(make_pair(e, r + 1)); 124 } 125 } 126 return rank; 127 } 128 vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) 129 { 130 auto tmp = scc(matrix); 131 auto g = tmp.first; 132 auto cmp = tmp.second; 133 auto rank = toposort(g); 134 int n = matrix.size(), m = matrix[0].size(); 135 vector<vector<int>> res(n, vector<int>(m, 0)); 136 for (int i = 0; i < n; i++) 137 { 138 for (int j = 0; j < m; j++) 139 { 140 int p = i * m + j; 141 int cmp_id = cmp[p]; 142 res[i][j] = rank[cmp_id]; 143 } 144 } 145 return res; 146 } 147 };