---
# System prepended metadata

title: '[LeetCode 1632. Rank Transform of a Matrix](https://leetcode.com/explore/challenge/card/august-leetcoding-challenge-2021/614/week-2-august-8th-august-14th/3874/)'

---

# [LeetCode 1632. Rank Transform of a Matrix](https://leetcode.com/explore/challenge/card/august-leetcoding-challenge-2021/614/week-2-august-8th-august-14th/3874/)
### Daily challenge Aug 8, 2021 (HARD)

>Given an `m x n matrix`, return a new matrix `answer` where `answer[row][col]` is the **rank** of `matrix[row][col]`.
>
>The rank is an integer that represents how large an element is compared to other elements. It is calculated using the following rules:
>
>* The rank is an integer starting from 1.
>* If two elements `p` and `q` are in the **same row or column**, then:
>* *  If **`p < q`** then **`rank(p) < rank(q)`**
>* * If **`p == q`** then **`rank(p) == rank(q)`**
>* * If **`p > q`** then **`rank(p) > rank(q)`**
>* The rank should be **as small as possible**.
>
>It is guaranteed that answer is unique under the given rules.

![](https://i.imgur.com/KWFYntI.png)

:::info
**Example 1:**
**Input:** matrix = [[1,2],[3,4]]
**Output:** [[1,2],[2,3]]
**Explanation:**
The rank of matrix[0][0] is 1 because it is the smallest integer in its row and column.
The rank of matrix[0][1] is 2 because matrix[0][1] > matrix[0][0] and matrix[0][0] is rank 1.
The rank of matrix[1][0] is 2 because matrix[1][0] > matrix[0][0] and matrix[0][0] is rank 1.
The rank of matrix[1][1] is 3 because matrix[1][1] > matrix[0][1], matrix[1][1] > matrix[1][0], and both matrix[0][1] and matrix[1][0] are rank 2.
:::

![](https://i.imgur.com/xGTUSU4.png)

:::info
**Example 2:**
**Input:** matrix = [[7,7],[7,7]]
**Output:** [[1,1],[1,1]]
:::

![](https://i.imgur.com/tkjmmgh.png)

:::info
**Example 3:**
**Input:** matrix = [[20,-21,14],[-19,4,19],[22,-47,24],[-19,4,19]]
**Output:** [[4,2,3],[1,3,4],[5,1,6],[1,3,4]]
:::

![](https://i.imgur.com/loUytZA.png)

:::info
**Example 4:**
**Input:** matrix = [[7,3,6],[1,4,5],[9,8,2]]
**Output:** [[5,1,4],[1,2,3],[6,3,1]]
:::

:::warning
**Constraints:**
* m == matrix.length
* n == matrix[i].length
* 1 <= m, n <= 500
* -109 <= matrix[row][col] <= 109
:::

---



### Approach 1 : Union Find
**`216 ms ( 83.58% )`** **`O( NNlog(MN) )`**

:::success
* 將元素的位置轉換成一維記錄到 **`map`** ---> **`index = i * n + j`**。
> m = 3, n = 3。
> row = 1, col = 1 ---> **`index = 1 * 3 + 1 = 4`**。
* **`root, rank`** 大小為 `m + n` 
---> **`0 ~ m - 1 = row`**。
---> **`m ~ m + n - 1 = col`**。
:::

:::success
**Union Find** : 
假設 `A 跟 B 一組`，給他們編號 `B`，後來又有 `B 跟 C 一組`，這時給他們編號 `C`，但是 `A` 也是跟 `B、C` 一組的，所以 `A` 同時也需要一起更新。

下面的方法會將 `row、col` 各做一次尋找。
:::

* **`map<int, vector<int>> list`** 紀錄所有元素的位置。
**`vector<int> rank(m + n, 0)`** 紀錄當前 `row、col` 的 `rank` 最大值。
**`vector<int> root(m + n, 0)`** 用於紀錄 `Union Find` 的組別。

1. 先將所有元素存入 `list`。
2. 因為 `list` 已經是排序過的，所以從頭開始遍歷，可以確保當前元素是最大值，接著判斷該元素下的所有 `index`。
> * 先將 `root` 初始化。
> * 接著使用 `Union Find` 將大小相同的元素分組，同時更新 `rank` 的最大值，判斷哪些 `col 或 row 相同`，他們的 `rank` 必須相同。
> * 透過剛剛的分組，賦予每個組別 `rank`。
> ---> **`rank2`** 紀錄下一輪的值，可以避免相同組別被賦予到不同的值，最後再丟回 **`rank`**。
>```cpp=38
>    rank2[i] = rank[group] + 1;
>    rank2[j + m] = rank[group] + 1;
>```

> 以 `2` 為例的 `Union Find`。
![](https://i.imgur.com/UbvALep.png)
![](https://i.imgur.com/7ovUmEg.png)
> 給 `rank` 值 ---> 找 `group`。
>![](https://i.imgur.com/PMxB7Uh.png)


```cpp=1
class Solution {
public:
    vector<vector<int>> matrixRankTransform(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        map<int, vector<int>> list;    // val, index
        
        for (int i=0; i<m; ++i) {
            for (int j=0; j<n; ++j) {
                list[matrix[i][j]].push_back(i * n + j);
            }
        }
        
        vector<int> rank(m + n, 0);
        vector<vector<int>> ans(m, vector<int>(n));
        
        for (auto & it : list) {
            vector<int> root(m + n, 0); // for Union find ( 0~n-1 = row / n ~ n+m-1 = col )
            for(int i=0; i<m+n; i++){
                root[i] = i;
            }

            // use Union find to find group
            for (auto & a: it.second) {
                int i = a / n, j = a % n;
                int r1 = find(root, i), r2 = find(root, j + m);
                
                root[r1] = r2;  // make row point to column
                rank[r2] = max(rank[r1], rank[r2]);
            }

            // set rank
            auto rank2 = rank;
            for (auto & a : it.second) {
                int i = a / n, j = a % n;
                int group = find(root, i);
                
                ans[i][j] = rank[group] + 1;
                rank2[i] = rank[group] + 1;
                rank2[j + m] = rank[group] + 1;
            }
            
            rank = rank2;
        }
        
        return ans;
    }
    
    // Union find
    int find(vector<int>& root, int x) {
        if (root[x] != x) root[x] = find(root, root[x]);    // update root[x]
        return root[x];
    }
};
```