拖了兩個月,終於這這道題目AC了。
思路是貪心,將所有的元素從小到大排序。並且維護兩個數組,一個數組代表每一行的當前已經填上的最大的rank,比如nrank[0]=2 表示第0行,目前已經填到了rank=2,下一個再填就一定是>=2的數字。
同理列也是。一開始nrank[],和mrank[]都賦值爲0。當我們貪心到一個元素的時候,它的rank,就是max(nrank[n], mrank[m])+1,
,
然後在遍歷所有元素的之前,我們需要用並查集把那些值相同並且行或者列相同的元素並起來,因爲這些元素的rank值一定相同。
所以在並查集裏,被合併的元素集合裏的rank是集合rank最大的哪個元素的rank值。
所以實現就要把一個一個集合裏的所有元素都算出它的rank,對於每一個集合都取一個最大值。那麼怎麼算rank,就是max(nrank[n], mrank[m])+1。當一個集合的rank確定之後,
再把集合裏的所有元素的rank都填上,相應的nrank[] 和mrank[]也要改變。這個過程我們放到遍歷所有從小到大排好序的數組中取實現。
最後終於過了。
還有一點,再遍歷之前的並查集操作,不能用N3的操作取並,只能N2*Log(N)
struct Node
{
int value;
int x;
int y;
Node() {}
Node(int x, int y, int value)
{
this->x = x;
this->y = y;
this->value = value;
}
}a[250005],b[505];
int compare(Node a, Node b)
{
return a.value < b.value;
}
class Solution {
public:
int n, m;
int rrank[505][505];
int nrank[505][505];
int mrank[505][505];
int f[250005];
int v[250005];
int rn[505];
int rm[505];
int tag[505][505];
int find(int x)
{
if (f[x] != x)
f[x] = find(f[x]);
return f[x];
}
void join(int x, int y)
{
int fx = find(x);
int fy = find(y);
f[fy] = fx;
}
vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) {
n = matrix.size();
m = matrix[0].size();
int pos = 0;
int pos2 = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
a[pos++] = Node(i, j, matrix[i][j]);
}
}
sort(a, a + pos, compare);
for (int i = 0; i < pos; i++)
{
tag[a[i].x][a[i].y] = i;
f[i] = i;
}
for (int i = 0; i < n; i++)
{
pos2 = 0;
for (int j = 0; j < m; j++)
{
b[pos2++] = Node(i, j, matrix[i][j]);
}
sort(b, b + pos2, compare);
for (int j = 1; j < pos2; j++)
{
if (b[j].value != b[j - 1].value)
{
continue;
}
else
{
int fx = find(tag[i][b[j - 1].y]);
int fy = find(tag[i][b[j].y]);
f[fx] = fy;
}
}
}
for (int i = 0; i < m; i++)
{
pos2 = 0;
for (int j = 0; j < n; j++)
{
b[pos2++] = Node(j, i, matrix[j][i]);
}
sort(b, b + pos2, compare);
for (int j = 1; j < pos2; j++)
{
if (b[j].value != b[j - 1].value)
{
continue;
}
else
{
int fx = find(tag[b[j-1].x][i]);
int fy = find(tag[b[j].x][i]);
f[fx] = fy;
}
}
}
int start = 0;
for (int i = 0; i < pos; i++)
{
int ran = max(rn[a[i].x], rm[a[i].y]) +1;
int ff = find(i);
if (v[ff] < ran)
{
v[ff] = ran;
}
if (i== pos-1 ||a[i + 1].value != a[i].value)
{
for (int j = start; j <= i; j++)
{
int xx = v[find(j)];
rrank[a[j].x][a[j].y] = xx;
rn[a[j].x] = xx;
rm[a[j].y] = xx;
}
start = i + 1;
}
}
vector<vector<int>> ans;
for (int i = 0; i < n; i++)
{
vector<int> res;
for (int j = 0; j < m; j++)
{
res.push_back(rrank[i][j]);
}
ans.push_back(res);
}
return ans;
}
};