携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情
每日刷题 2022.08.29
- leetcode原题链接:leetcode.cn/problems/bu…
- 难度:困难
- 方法:拓扑排序
题目
- 给你一个 正 整数 k ,同时给你:
- 一个大小为 n 的二维整数数组 rowConditions ,其中 rowConditions[i] = [abovei, belowi] 和
- 一个大小为 m 的二维整数数组 colConditions ,其中 colConditions[i] = [lefti, righti] 。
- 两个数组里的整数都是 1 到 k 之间的数字。
- 你需要构造一个 k x k 的矩阵,1 到 k 每个数字需要 恰好出现一次 。剩余的数字都是 0 。
- 矩阵还需要满足以下条件:
- 对于所有 0 到 n - 1 之间的下标 i ,数字 abovei 所在的 行 必须在数字 belowi 所在行的上面。
- 对于所有 0 到 m - 1 之间的下标 i ,数字 lefti 所在的 列 必须在数字 righti 所在列的左边。
- 返回满足上述要求的 任意 矩阵。如果不存在答案,返回一个空的矩阵。
示例
- 示例1
输入:k = 3, rowConditions = [[1,2],[3,2]], colConditions = [[2,1],[3,2]]
输出:[[3,0,0],[0,0,1],[0,2,0]]
解释:上图为一个符合所有条件的矩阵。
行要求如下:
- 数字 1 在第 1 行,数字 2 在第 2 行,1 在 2 的上面。
- 数字 3 在第 0 行,数字 2 在第 2 行,3 在 2 的上面。
列要求如下:
- 数字 2 在第 1 列,数字 1 在第 2 列,2 在 1 的左边。
- 数字 3 在第 0 列,数字 2 在第 1 列,3 在 2 的左边。
注意,可能有多种正确的答案。
- 示例2
输入:k = 3, rowConditions = [[1,2],[2,3],[3,1],[2,3]], colConditions = [[2,1]]
输出:[]
解释:由前两个条件可以得到 3 在 1 的下面,但第三个条件是 3 在 1 的上面。
没有符合条件的矩阵存在,所以我们返回空矩阵。
提示
- 2 <= k <= 400
- 1 <= rowConditions.length, colConditions.length <= 10^4
- rowConditions[i].length == colConditions[i].length == 2
- 1 <= abovei, belowi, lefti, righti <= k
- abovei != belowi
- lefti != righti
解题思路
- 根据题意可知:题目中会给出节点的个数
k、上下的关系rowConditions数组中展示,左右的关系colconditions数组中展示,需要根据这些信息创建一个k * k的矩阵。 - 那么就根据上下的关系,使用拓扑排序生成一个序列;根据左右的关系,使用拓扑排序生成一个序列。上下关系生成的序列下标作为矩阵的纵坐标,左右生成的序列下标作为矩阵的横坐标。将横纵坐标结合起来,就可以直到每个数在矩阵中的位置。
- 注:拓扑排序可能会存在多种可能的序列,即:存在多个入度为
0的节点,那么就随机选择一种就可以了。 - 注:因为可能存在环,举例:
3节点既在2节点的上面,2节点又在3节点的上面,本身就是矛盾的,因此其不可能存在一个包含所有整数1 ~ k的序列,即:没有符合条件的矩阵存在,返回空矩阵。 - 因为存在多次使用拓扑排序的情况,可以将拓扑排序实现部分封装成函数调用
find
AC代码
var buildMatrix = function(k, row, col) {
let ans = new Array(k).fill(0).map(() => new Array(k).fill(0));
let r = find(row), l = find(col);
if(r.length === 0 || l.length === 0) return [];
for(let i = 1; i <= k; i++) {
let x = r.indexOf(i), y = l.indexOf(i);
ans[x][y] = i;
}
return ans;
function find(curArr) {
let n = curArr.length, edge = new Array(k + 1).fill(0);
let grap = new Array(k + 1).fill(0).map(() => new Array());
for(let i = 0; i < n; i++) {
let pre = curArr[i][0], nxt = curArr[i][1];
grap[pre].push(nxt);
edge[nxt]++;
}
let queue = [];
for(let i = 1; i <= k + 1; i++) {
if(edge[i] === 0) queue.push(i);
}
let shuzu = [];
while(queue.length != 0) {
let cur = queue.pop(), len = grap[cur].length;
shuzu.push(cur);
while(len > 0) {
let nxtt = grap[cur][len - 1];
edge[nxtt]--;
if(edge[nxtt] === 0) queue.push(nxtt);
len--;
}
}
if(shuzu.length !== k) return [];
return shuzu;
}
};