LeetCode 1632. Rank Transform of a Matrix
拖了两个月,终于这这道题目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;
}
};