(H1632 - Rank Transform of a Matrix) 순서 강제 + Union-Find
이 문제를 rule-based 풀이로 풀려고 하면 답이 없음.
왜냐면, 한 row 혹은 column의 rank를 맞춰놔도, 다른 row 혹은 column에 의해 영향을 받을 수 있기 때문.
풀이의 핵심 논리는 아래 포스팅에 잘 설명되어 있다.
💡 핵심 :
정렬해서 순서 강제 (낮은 숫자부터 rank 매기기)
+ Union-Find (같은 숫자는 같은 rank)
+ Hint 2 (row, col 단위로 rank 관리)
1. 배열의 최솟값에 rank 1이 매겨지는 것은 자명하다. 그리고 숫자가 커질수록 rank가 높아질 확률이 있겠지.
→ 작은 숫자들부터 rank 매기자. 순서 강제.
구현 : map<숫자, 위치배열> 식으로 오름차순 정렬된 상태로 숫자별 위치 정리해서 오름차순 처리
2. 동일 row, col에 있는 같은 숫자는 동일한 rank를 매겨야 한다는 조건
→Union-Find 사용해서 동일 row, col에 있는 같은 숫자는 같은 그룹으로 묶고, 그룹별로 rank 매기자.
구현 : 각 row와 column을 각각 그룹으로 본다.
row N + col M 크기의 DisjointSet 생성 후, (x,y)에 숫자가 나타날 경우 row x와 col y를 같은 그룹으로 묶는다.
이러면 나중에 또 x나 y에 같은 숫자 나타나도 동일 그룹에 있는 걸로 처리되겠지.
3. 각 cell별로 rank 매기는게 아니라, row/col 단위로 max rank 관리
→ 1번 조건에 의해 rank는 계속 증가하는 방향으로 업데이트 됨 + Hint2를 생각하면 이 방식으로 맞는 rank를 찾아낸다는 것을 알 수 있음
구현 : vi rank(N + M, 0), group_rank(N + M, 0);
group_rank는 약간 중간 계산 값을 저장하기 위한 tmp 공간 느낌
vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) { int N = matrix.size(), M = matrix[0].size(); auto to_pos = [&](int x, int y) { return x * M + y; }; vector<vector<int>> ans(N, vi(M, 0)); map<int, vector<pii>> d; // value : {locations in (x,y)} // 1. Init - sort using map FOR(x, 0, N) FOR(y, 0, M) { d[matrix[x][y]].emplace_back(x, y); } vi rank(N + M, 0); // track max ranks of row (idx 0~N-1) & col (idx N~) vi group_rank(N + M, 0); // rank assigned // ★ rank는 0으로 초기화 - 업데이트 시 max에 안걸리게 // From smallest number for (const auto& kv : d) { int num = kv.first; const vector<pii>& v = kv.second; // 2. Find groups DisjointSet dsu(N+M); // ★ track connected rows and cols for (const pii& p : v) { auto [x, y] = p; dsu.Union(x, N + y); // row 'x' and column 'y' connected by current element } // 3. Find group rank for (const pii& p : v) { auto [x, y] = p; int g = dsu.Find(x); int& gRank = group_rank[g]; gRank = max({ gRank, rank[x] + 1, rank[N + y] + 1 }); } // 4. Update result and fill ans for (const pii& p : v) { auto [x, y] = p; int g = dsu.Find(x); int gRank = group_rank[g]; rank[x] = max(rank[x], gRank); rank[N + y] = max(rank[N + y], gRank); ans[x][y] = gRank; } } return ans; }
'<PS> > [복기 - LeetCode]' 카테고리의 다른 글
(H312 - Burst Balloons) DP 이전정보 + reverse thinking (0) | 2021.08.19 |
---|---|
(H546 - Remove Boxes) DP 이전정보 처리하기 ★ (0) | 2021.08.17 |
(H-827 Making A Large Island) 단순 채우기 BFS 재귀 코드 (0) | 2021.08.02 |
(H - 1203. Sort Items by Groups Respecting Dependencies) Two-level 위상정렬 (0) | 2021.07.15 |
(M - 375. Guess Number Higher or Lower II) Minmax (0) | 2021.07.03 |