[周赛308:拓扑排序] 2392. 给定条件下构造矩阵

176 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情

每日刷题 2022.08.29

题目

  • 给你一个 正 整数 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

image.png

输入: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 行,12 的上面。
- 数字 3 在第 0 行,数字 2 在第 2 行,32 的上面。
列要求如下:
- 数字 2 在第 1 列,数字 1 在第 2 列,21 的左边。
- 数字 3 在第 0 列,数字 2 在第 1 列,32 的左边。
注意,可能有多种正确的答案。
  • 示例2
输入:k = 3, rowConditions = [[1,2],[2,3],[3,1],[2,3]], colConditions = [[2,1]]
输出:[]
解释:由前两个条件可以得到 31 的下面,但第三个条件是 31 的上面。
没有符合条件的矩阵存在,所以我们返回空矩阵。

提示

  • 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;
  }
};