变为棋盘

200 阅读2分钟

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

782. 变为棋盘 - 力扣(LeetCode)

一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。

返回 将这个矩阵变为  “棋盘”  所需的最小移动次数 。如果不存在可行的变换,输出 -1

“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。

示例 1:


输入: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
输出: 2
解释: 一种可行的变换方式如下,从左到右:
第一次移动交换了第一列和第二列。
第二次移动交换了第二行和第三行。

示例 2:


输入: board = [[0, 1], [1, 0]]
输出: 0
解释: 注意左上角的格值为0时也是合法的棋盘,也是合法的棋盘.

示例 3:


输入: board = [[1, 0], [1, 0]]
输出: -1
解释: 任意的变换都不能使这个输入变为合法的棋盘。

提示:

  • n == board.length
  • n == board[i].length
  • 2 <= n <= 30
  • board[i][j] 将只包含 0或 1

解题

/**
 * @param {number[][]} board
 * @return {number}
 */
var movesToChessboard = function (board) {
  const h = new Map();
  const v = new Map();
  const len = board.length;
  const num = Math.pow(2, len) - 1;
  const setMap = (v, map, i) => {
    let item = map.get(v);
    if (item) {
      item.push(i);
    } else if (map.size >= 2) {
      return false;
    } else {
      map.set(v, [i]);
    }
    return true;
  };
  const valid = (arr) => {
    if (arr.length != 2 || (arr[0][0] ^ arr[1][0]) != num) return false;
    const diff = Math.abs(arr[0][1].length - arr[1][1].length);
    if (diff > 1) return false;
    return true;
  };
  const getCount = (arr) => {
    let oddCount = 0;
    let midCount = ((len + 1) >> 1) | 0;
    for (let i = 0; i < arr[0][1].length; i++) {
      if (arr[0][1][i] & 1) {
        oddCount++;
      }
    }
    if (len & 1) {
      if (midCount === arr[0][1].length) {
        return oddCount;
      } else {
        return midCount - 1 - oddCount;
      }
    } else {
      return Math.min(oddCount, midCount - oddCount);
    }
  };
  for (let i = 0; i < len; i++) {
    let hValue = 0;
    let vValue = 0;
    for (let j = 0; j < len; j++) {
      hValue = (hValue << 1) + board[i][j];
      vValue = (vValue << 1) + board[j][i];
    }
    if (!setMap(hValue, h, i) || !setMap(vValue, v, i)) return -1;
  }
  const hArr = Array.from(h);
  const vArr = Array.from(v);
  if (!valid(hArr) || !valid(vArr)) return -1;
  return getCount(hArr) + getCount(vArr);
};