Build a Matrix With Conditions

Build a Matrix With Conditions

You are given a positive integer $k$. You are also given:

  • a 2D integer array $rowConditions$ of size $n$ where $rowConditions[i] = [{above}_i, {below}_i]$, and
  • a 2D integer array $colConditions$ of size $m$ where $colConditions[i] = [{left}_i, {right}_i]$.

he two arrays contain integers from $1$ to $k$.

You have to build a $k \times k$ matrix that contains each of the numbers from $1$ to $k$ exactly once. The remaining cells should have the value $0$.

The matrix should also satisfy the following conditions:

  • The number ${above}_i$ should appear in a row that is strictly above the row at which the number ${below}_i$ appears for all $i$ from $0$ to $n - 1$.
  • The number ${left}_i$ should appear in a column that is strictly left of the column at which the number ${right}_i$ appears for all $i$ from $0$ to $m - 1$.

Return any matrix that satisfies the conditions. If no answer exists, return an empty matrix.

Example 1:

Input: k = 3, rowConditions = [[1,2],[3,2]], colConditions = [[2,1],[3,2]]
Output: [[3,0,0],[0,0,1],[0,2,0]]
Explanation: The diagram above shows a valid example of a matrix that satisfies all the conditions.
The row conditions are the following:
- Number 1 is in row 1, and number 2 is in row 2, so 1 is above 2 in the matrix.
- Number 3 is in row 0, and number 2 is in row 2, so 3 is above 2 in the matrix.
The column conditions are the following:
- Number 2 is in column 1, and number 1 is in column 2, so 2 is left of 1 in the matrix.
- Number 3 is in column 0, and number 2 is in column 1, so 3 is left of 2 in the matrix.
Note that there may be multiple correct answers.

Example 2:

Input: k = 3, rowConditions = [[1,2],[2,3],[3,1],[2,3]], colConditions = [[2,1]]
Output: []
Explanation: From the first two conditions, 3 has to be below 1 but the third conditions needs 3 to be above 1 to be satisfied.
No matrix can satisfy all the conditions, so we return the empty matrix.

Constraints:

$2 \leq k \leq 400$
$1 \leq rowConditions.length, colConditions.length \leq {10}^4$
$rowConditions[i].length == colConditions[i].length == 2$
$1 \leq {above}_i, {below}_i, {left}_i, {right}_i \leq k$
${above}_i \ne {below}_i$
${left}_i \ne {right}_i$

 

解题思路

  比赛的时候思路都想出来了,就是拓扑排序,但代码就是没写出来,硬是调试了快一个小时也没写出来。

  首先可以发现每个数字摆放在哪一行与哪一列是相互独立的,因此可以分别求每一行分别放哪些数,每一列分别放哪些数。

  题目给的限制条件可以抽象出一个图,如果有$\{ {a, b} \}$,意味着$a$要比$b$大,那么就有一条从$a$指向$b$的边。把所有的限制条件建出图后对这个图跑一遍拓扑排序,看看有没有环。如果有环意味着之前给出的条件存在矛盾,等价于无解。如果没有环那么最后得到的拓扑序就是每个数字在答案矩阵中的行$/$列坐标。

  AC代码如下:

 1 class Solution {
 2 public:
 3     int n;
 4 
 5     vector<int> topsort(vector<vector<int>> &v) {
 6         vector<vector<int>> g(n + 1);
 7         vector<int> deg(n + 1);
 8         for (auto &p : v) {
 9             g[p[0]].push_back(p[1]);
10             deg[p[1]]++;
11         }
12 
13         queue<int> q;
14         for (int i = 1; i <= n; i++) {
15             if (deg[i] == 0) q.push(i);
16         }
17         vector<int> ret;
18         while (!q.empty()) {
19             int t = q.front();
20             q.pop();
21             ret.push_back(t);
22             for (auto &it : g[t]) {
23                 if (--deg[it] == 0) q.push(it);
24             }
25         }
26 
27         return ret;
28     }
29 
30     vector<vector<int>> buildMatrix(int k, vector<vector<int>>& rowConditions, vector<vector<int>>& colConditions) {
31         n = k;
32         auto q1 = topsort(rowConditions);
33         auto q2 = topsort(colConditions);
34         if (q1.size() < n || q2.size() < n) return {};
35 
36         vector<vector<int>> ans(n, vector<int>(n));
37         for (int i = 1; i <= n; i++) {
38             ans[find(q1.begin(), q1.end(), i) - q1.begin()][find(q2.begin(), q2.end(), i) - q2.begin()] = i;
39         }
40         return ans;
41     }
42 };

  其实一开始看到这题我首先想到的是用floyd求传递闭包,时间复杂度是$O(k^3)$,大概率会超时,实际跑了一下确实会超时,不过这种做法是正确的。

  一样根据约束条件建有向图,然后跑floyd求传递闭包,如果有矛盾的话此时必然存在某个数$x$有$g[x][x] == true$,即有$x > x$,这个肯定是有矛盾的。

  TLE代码如下:

 1 class Solution {
 2 public:
 3     int n;
 4 
 5     vector<int> floyd(vector<vector<int>> &v) {
 6         vector<vector<bool>> g(n + 1, vector<bool>(n + 1));
 7         for (auto &p : v) {
 8             g[p[0]][p[1]] = true;
 9         }
10 
11         for (int k = 1; k <= n; k++) {
12             for (int i = 1; i <= n; i++) {
13                 for (int j = 1; j <= n; j++) {
14                     g[i][j] = g[i][j] | g[i][k] & g[k][j];  // leetcode上不知道为什么写成g[i][j] |= g[i][k] & g[k][j];会报错
15                 }
16             }
17         }
18 
19         for (int i = 1; i <= n; i++) {
20             if (g[i][i]) return {};
21         }
22 
23         vector<int> ret;
24         vector<bool> vis(n + 1);
25         for (int k = 1; k <= n; k++) {
26             int maxv = -1, idx;
27             for (int i = 1; i <= n; i++) {
28                 if (!vis[i]) {
29                     int t = 0;
30                     for (int j = 1; j <= n; j++) {
31                         if (!vis[j] && g[i][j]) t++;
32                     }
33                     if (t > maxv) maxv = t, idx = i;
34                 }
35             }
36             ret.push_back(idx);
37             vis[idx] = true;
38         }
39 
40         return ret;
41     }
42 
43     vector<vector<int>> buildMatrix(int k, vector<vector<int>>& rowConditions, vector<vector<int>>& colConditions) {
44         n = k;
45         auto q1 = floyd(rowConditions);
46         auto q2 = floyd(colConditions);
47         if (q1.empty() || q2.empty()) return {};
48 
49         vector<vector<int>> ans(n, vector<int>(n));
50         for (int i = 1; i <= n; i++) {
51             ans[find(q1.begin(), q1.end(), i) - q1.begin()][find(q2.begin(), q2.end(), i) - q2.begin()] = i;
52         }
53         return ans;
54     }
55 };

 

参考资料

  力扣第308场周赛:https://www.bilibili.com/video/BV1aW4y1t7Gd

posted @ 2022-08-28 15:41  onlyblues  阅读(36)  评论(0编辑  收藏  举报
Web Analytics