LeetCode //C - 782. Transform to Chessboard

782. Transform to Chessboard

You are given an n x n binary grid board. In each move, you can swap any two rows with each other, or any two columns with each other.

Return the minimum number of moves to transform the board into a chessboard board. If the task is impossible, return -1.

A chessboard board is a board where no 0’s and no 1’s are 4-directionally adjacent.
 

Example 1:

Input: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
Output: 2
Explanation: One potential sequence of moves is shown.
The first move swaps the first and second column.
The second move swaps the second and third row.

Example 2:

Input: board = [[0,1],[1,0]]
Output: 0
Explanation: Also note that the board with 0 in the top left corner, is also a valid chessboard.

Example 3:

Input: board = [[1,0],[1,0]]
Output: -1
Explanation: No matter what sequence of moves you make, you cannot end with a valid chessboard.

Constraints:
  • n == board.length
  • n == board[i].length
  • 2 <= n <= 30
  • board[i][j] is either 0 or 1.

From: LeetCode
Link: 782. Transform to Chessboard


Solution:

Ideas:

1. Convert the first row and column to bitmasks:

  • Represent board[0] as rowMask, and board[:,0] as colMask.

2. Calculate their bitwise inverses:

  • reverseRowMask = ~rowMask, within n bits.
  • reverseColMask = ~colMask, within n bits.

3. Validate each row and column:

  • Every row must match either rowMask or reverseRowMask.
  • Every column must match either colMask or reverseColMask.
  • If any row/column doesn’t match, return -1 (invalid board).

4. Count how many rows and columns match rowMask and colMask:

  • Needed for balancing parity (how many of each type must exist).

5. Compute minimum swaps using helper getMoves():

  • Count how many positions are out of place compared to ideal alternating masks (e.g. 010101… or 101010…).
  • If n is even, either pattern is valid; choose the one with fewer swaps.
  • If n is odd, only one alternating pattern is valid (depends on parity of 1’s).

6. Return total moves:

  • If either getMoves result is -1, return -1 (impossible).
  • Otherwise, return rowMoves + colMoves.
Code:
int popcount(int x) {
    int count = 0;
    while (x) {
        count += x & 1;
        x >>= 1;
    }
    return count;
}

int getMoves(int mask, int count, int n) {
    int ones = popcount(mask);
    int maskA = 0xAAAAAAAA & ((1 << n) - 1);
    int mask5 = 0x55555555 & ((1 << n) - 1);

    if (n % 2 == 0) {
        if (ones != n / 2 || count != n / 2) return -1;
        int swap0 = popcount(mask ^ maskA);
        int swap1 = popcount(mask ^ mask5);
        return swap0 < swap1 ? swap0 / 2 : swap1 / 2;
    } else {
        if (abs(n - 2 * ones) != 1 || abs(n - 2 * count) != 1) return -1;
        int ideal = (ones == n / 2) ? maskA : mask5;
        return popcount(mask ^ ideal) / 2;
    }
}

int movesToChessboard(int** board, int boardSize, int* boardColSize){
    int n = boardSize;
    int rowMask = 0, colMask = 0;

    for (int i = 0; i < n; ++i) {
        rowMask |= (board[0][i] << i);
        colMask |= (board[i][0] << i);
    }

    int reverseRowMask = ((1 << n) - 1) ^ rowMask;
    int reverseColMask = ((1 << n) - 1) ^ colMask;
    int rowCnt = 0, colCnt = 0;

    for (int i = 0; i < n; ++i) {
        int currRowMask = 0, currColMask = 0;
        for (int j = 0; j < n; ++j) {
            currRowMask |= (board[i][j] << j);
            currColMask |= (board[j][i] << j);
        }

        if (currRowMask != rowMask && currRowMask != reverseRowMask) return -1;
        if (currColMask != colMask && currColMask != reverseColMask) return -1;
        if (currRowMask == rowMask) rowCnt++;
        if (currColMask == colMask) colCnt++;
    }

    int rowMoves = getMoves(rowMask, rowCnt, n);
    int colMoves = getMoves(colMask, colCnt, n);
    if (rowMoves == -1 || colMoves == -1) return -1;

    return rowMoves + colMoves;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Navigator_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值