leetcode1632 矩阵转换后的秩

思路:

整体思路是将矩阵中每个元素当作一个点,根据大小关系构造有向图之后进行拓扑排序。由于题目要求每一行(列)中相等的元素的秩要相等,所以在建图的时候考虑把这样的元素对应的点合并成一个点。具体实现使用并查集或者强连通分量缩点都可以。

实现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 };
原文地址:https://www.cnblogs.com/wangyiming/p/14354740.html