Talentd
FleetCode
Make and follow sheets.Sign in

Transform to Chessboard solution and explanation

HardArrayBit ManipulationMathMatrix8 min read51.9% acceptanceUpdated 9 Apr 2026
Transform to Chessboard | Leetcode 782 | Live coding session 🔥🔥🔥Coding Decoded · 15:15 · 3K viewsWatch on YouTube
9 more videos on this problem
  1. Transform to Chessboard | Leetcode 782 | Live coding session 🔥🔥🔥Coding Decoded · 15:15 · 3K views
  2. LeetCode 782. Transform to ChessboardHappy Coding · 30:10 · 1K views
  3. Leetcode - Transform to Chessboard (Python)Timothy H Chang · 16:57 · 1K views
  4. 【每日一题】782. Transform to Chessboard, 1/15/2020Huifeng Guan · 57:49 · 673 views
  5. Daily Leetcode #544: Sep 26, 2021 - 782. Transform to ChessboardProgramming Live with Larry · 1:01:28 · 531 views
  6. Leetcode 782 - Transform to ChessboardSkillUp with Genie · 18:41 · 435 views
  7. Leetcode 0782. Transform to ChessboardFearless Learner · 20:12 · 327 views
  8. Day 26/30 | Transform to Chessboard | September LeetCoding Challenge 2021 | C++Ascorbichelix · 27:41 · 190 views
  9. 782 Transform to Chessboard CPP SolutionAnimated Anand · 14:29 · 105 views
  10. Leetcode 782. Transform to Chessboard (Daily Challenge 09/26/2021)Yinghua Hu · 30:28 · 59 views

The problem

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.

Approach overview

Problem Overview: You are given an n x n binary matrix. The task is to transform it into a valid chessboard pattern (alternating 0s and 1s in rows and columns) using the minimum number of row or column swaps. If the transformation is impossible, return -1.

Approach 1: Pattern Matching and Position Swapping (O(n^2) time, O(1) space)

A valid chessboard has exactly two types of rows and two types of columns, and they must be bitwise inverses of each other. Start by comparing every row with the first row and every column with the first column. Any row must either match the first row or be its inverse; otherwise the configuration cannot become a chessboard. After validating this constraint, count how many rows and columns are misplaced relative to the expected alternating pattern. The minimum swaps are determined by comparing the matrix with two possible chessboard patterns (starting with 0 or starting with 1). Implementation often uses bit masks or parity checks to count mismatches efficiently. This approach works directly on the array representation of the matrix and runs in O(n^2) because every cell is inspected once.

Approach 2: Recursive Approach with Memoization (O(n^2) time, O(n^2) space)

This approach treats the board transformation as a recursive state exploration problem. At each step, you attempt swapping rows or columns that violate the chessboard pattern. The recursion evaluates whether the current configuration can reach a valid state with minimal operations. Memoization stores previously computed board states (often serialized as bit patterns) to avoid recomputation. Although recursion introduces overhead, caching ensures the algorithm does not repeatedly explore identical states. This strategy highlights the structural constraints of alternating patterns and demonstrates how bit manipulation can encode rows and columns compactly for memo keys.

Approach 3: Iterative Approach with Tabulation (O(n^2) time, O(n) space)

The tabulation method computes valid row and column placements iteratively. Instead of recursion, it counts the number of 1s in rows and columns and verifies that counts differ by at most one, which is required for alternating patterns. Then it iterates through indices and calculates how many positions violate the expected parity pattern ((i + j) % 2). Using these mismatch counts, the algorithm derives the minimal swaps required for rows and columns separately. This method avoids recursion overhead and keeps memory usage small while still leveraging the structure of alternating grids. It is easier to implement in iterative languages and works well when you want deterministic state progression.

Recommended for interviews: The pattern matching and position swapping approach is the standard solution interviewers expect. It shows you understand the mathematical constraints of chessboard patterns and can derive swap counts using parity checks. Recursive exploration demonstrates reasoning about state transitions, but the optimal solution proves stronger algorithmic insight and runs with minimal space.

Approach 1: Pattern Matching and Position Swapping

This approach involves matching the row and column patterns against a valid chessboard configuration and calculating the minimum number of swaps needed. The idea is to compare the current board's rows and columns to the two possible valid chessboard row and column patterns.

def movesToChessboard(board):
    n = len(board)

    def movesToTransform(line):
        ones = sum(line)
        if not (n // 2 <= ones <= (n + 1) // 2):
            return float('inf')  # Not possible to transform to a line

        line1Count = sum(line[i] == i % 2 for i in range(n))
        line2Count = sum(line[i] != i % 2 for i in range(n))

        if n % 2:
            # Odd size board, should have a dominant line pattern
            if line1Count % 2:
                return n - line2Count
            return n - line1Count
        return min(n - line1Count, n - line2Count)

    # Check if transformation possible
    firstRow = board[0]
    if any(set(board[i]) != set(firstRow) for i in range(n)):
        return -1

    firstColumn = [board[i][0] for i in range(n)]
    if any(set([board[i][j] for i in range(n)]) != set(firstColumn) for j in range(n)):
        return -1

    rowMoves = movesToTransform([board[i] for i in range(n)])
    colMoves = movesToTransform([board[i][0] for i in range(n)])
    return (rowMoves + colMoves) // 2
public int movesToChessboard(int[][] board) {
    int n = board.length;
    // Helper method
    int getTransformMoves(int[] line) {
        int count = 0, n = line.length;
        for (int i = 0; i < n; i++) {
            if (line[i] == i % 2) count++;
        }
        return count;
    }
    ...

The function movesToChessboard attempts to transform the given board into a chessboard. It determines if the transformation is possible by verifying the row and column patterns. The pattern matching checks if the lines have the correct number of 1s or 0s to resemble a chessboard line pattern. movesToTransform calculates the minimum swaps needed to align each row and column pattern to either of two potential chessboard patterns.

Complexity

Time Complexity: O(n2) due to examining each cell multiple times for pattern matching.
Space Complexity: O(n) for storing intermediate lists.

Try this approach in the editor

Approach 2: Recursive Approach with Memoization

Recursive Approach with Memoization:

This approach involves breaking the problem down into smaller subproblems, solving each using recursion, and storing the results of these subproblems to avoid redundant calculations. This is a classic dynamic programming approach that trades time complexity for space complexity by using a cache to remember previously computed results.

Memoization helps in optimizing the recursive calls by saving the results of subproblems, making future calls faster and reducing time complexity significantly.

def fibonacci(n, memo={}):
    if n <= 1:
        return n
    if n not in memo:
        memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo)
    return memo[n]
#include <stdio.h>
#define MAX 1000

int memo[MAX] = {0};

int fibonacci(int n) {
    if (n <= 1)
        return n;
    if (memo[n] == 0)
        memo[n] = fibonacci(n - 1) + fibonacci(n - 2);
    return memo[n];
}

This Python solution makes use of a dictionary, memo, to store computed Fibonacci numbers. The base cases are n = 0 and n = 1 where the function returns the number itself. For other cases, the result is calculated recursively and stored in the memo dictionary.

Complexity

Time Complexity: O(n)
Space Complexity: O(n) due to the recursion call stack and memoization dictionary.

Try this approach in the editor

Approach 3: Iterative Approach with Tabulation

Iterative Approach with Tabulation:

This approach uses an iterative method to fill up a table (array), which stores previously computed values of the subproblems (in this case, Fibonacci numbers). Tabulation is another form of dynamic programming where you solve the problem iteratively and build the solution bottom-up.

This approach optimizes space usage by using only an array of size n or even reducing it to constant space by utilizing only the last two computed values.

public class Fibonacci {
    public static int fibonacci(int n) {
        if (n <= 1) return n;
        int[] fib = new int[n + 1];
        fib[0] = 0;
        fib[1] = 1;
        for (int i = 2; i <= n; i++) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
        return fib[n];
    }
}
function fibonacci(n) {
    if (n <= 1) return n;
    let fib1 = 0, fib2 = 1, fibResult = 0;
    for (let i = 2; i <= n; i++) {
        fibResult = fib1 + fib2;
        fib1 = fib2;
        fib2 = fibResult;
    }
    return fibResult;
}

The Java approach uses an array fib to store Fibonacci numbers calculated in sequence. The for loop computes values from the bottom-up, storing each result to be used in subsequent calculations.

Complexity

Time Complexity: O(n)
Space Complexity: O(n) due to the storage of the entire Fibonacci sequence up to fib[n].

Try this approach in the editor

Approach 4: Pattern Observation + State Compression

In a valid chessboard, there are exactly two types of "rows".

For example, if one row on the chessboard is "01010011", then any other row can only be "01010011" or "10101100". Columns also satisfy this property.

Additionally, each row and each column has half 0s and half 1s. Suppose the chessboard is n times n:

  • If n = 2 times k, then each row and each column has k 1s and k 0s.
  • If n = 2 times k + 1, then each row has k 1s and k + 1 0s, or k + 1 1s and k 0s.

Based on the above conclusions, we can determine whether a chessboard is valid. If valid, we can calculate the minimum number of moves required.

If n is even, there are two possible valid chessboards, where the first row is either "010101..." or "101010...". We calculate the minimum number of swaps required for these two possibilities and take the smaller value as the answer.

If n is odd, there is only one possible valid chessboard. If the number of 0s in the first row is greater than the number of 1s, then the first row of the final chessboard must be "01010..."; otherwise, it must be "10101...". We calculate the number of swaps required and use it as the answer.

The time complexity is O(n^2), where n is the size of the chessboard. The space complexity is O(1).

class Solution {
public:
    int n;
    int movesToChessboard(vector<vector<int>>& board) {
        n = board.size();
        int mask = (1 << n) - 1;
        int rowMask = 0, colMask = 0;
        for (int i = 0; i < n; ++i) {
            rowMask |= board[0][i] << i;
            colMask |= board[i][0] << i;
        }
        int revRowMask = mask ^ rowMask;
        int revColMask = mask ^ colMask;
        int sameRow = 0, sameCol = 0;
        for (int i = 0; i < n; ++i) {
            int curRowMask = 0, curColMask = 0;
            for (int j = 0; j < n; ++j) {
                curRowMask |= board[i][j] << j;
                curColMask |= board[j][i] << j;
            }
            if (curRowMask != rowMask && curRowMask != revRowMask) return -1;
            if (curColMask != colMask && curColMask != revColMask) return -1;
            sameRow += curRowMask == rowMask;
            sameCol += curColMask == colMask;
        }
        int t1 = f(rowMask, sameRow);
        int t2 = f(colMask, sameCol);
        return t1 == -1 || t2 == -1 ? -1 : t1 + t2;
    }

    int f(int mask, int cnt) {
        int ones = __builtin_popcount(mask);
        if (n & 1) {
            if (abs(n - ones * 2) != 1 || abs(n - cnt * 2) != 1) return -1;
            if (ones == n / 2) return n / 2 - __builtin_popcount(mask & 0xAAAAAAAA);
            return (n + 1) / 2 - __builtin_popcount(mask & 0x55555555);
        } else {
            if (ones != n / 2 || cnt != n / 2) return -1;
            int cnt0 = (n / 2 - __builtin_popcount(mask & 0xAAAAAAAA));
            int cnt1 = (n / 2 - __builtin_popcount(mask & 0x55555555));
            return min(cnt0, cnt1);
        }
    }
};
func movesToChessboard(board [][]int) int {
	n := len(board)
	mask := (1 << n) - 1
	rowMask, colMask := 0, 0
	for i := 0; i < n; i++ {
		rowMask |= board[0][i] << i
		colMask |= board[i][0] << i
	}
	revRowMask := mask ^ rowMask
	revColMask := mask ^ colMask
	sameRow, sameCol := 0, 0
	for i := 0; i < n; i++ {
		curRowMask, curColMask := 0, 0
		for j := 0; j < n; j++ {
			curRowMask |= board[i][j] << j
			curColMask |= board[j][i] << j
		}
		if curRowMask != rowMask && curRowMask != revRowMask {
			return -1
		}
		if curColMask != colMask && curColMask != revColMask {
			return -1
		}
		if curRowMask == rowMask {
			sameRow++
		}
		if curColMask == colMask {
			sameCol++
		}
	}
	f := func(mask, cnt int) int {
		ones := bits.OnesCount(uint(mask))
		if n%2 == 1 {
			if abs(n-ones*2) != 1 || abs(n-cnt*2) != 1 {
				return -1
			}
			if ones == n/2 {
				return n/2 - bits.OnesCount(uint(mask&0xAAAAAAAA))
			}
			return (n+1)/2 - bits.OnesCount(uint(mask&0x55555555))
		} else {
			if ones != n/2 || cnt != n/2 {
				return -1
			}
			cnt0 := n/2 - bits.OnesCount(uint(mask&0xAAAAAAAA))
			cnt1 := n/2 - bits.OnesCount(uint(mask&0x55555555))
			return min(cnt0, cnt1)
		}
	}
	t1 := f(rowMask, sameRow)
	t2 := f(colMask, sameCol)
	if t1 == -1 || t2 == -1 {
		return -1
	}
	return t1 + t2
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Pattern Matching and Position Swapping

Time Complexity: O(n2) due to examining each cell multiple times for pattern matching.
Space Complexity: O(n) for storing intermediate lists.

Recursive Approach with Memoization

Time Complexity: O(n)
Space Complexity: O(n) due to the recursion call stack and memoization dictionary.

Iterative Approach with Tabulation

Time Complexity: O(n)
Space Complexity: O(n) due to the storage of the entire Fibonacci sequence up to fib[n].

Pattern Observation + State Compression–

Complexity analysis

ApproachTimeSpaceWhen to Use
Pattern Matching and Position SwappingO(n^2)O(1)Best general solution. Efficiently validates row/column patterns and computes minimal swaps.
Recursive Approach with MemoizationO(n^2)O(n^2)Useful for understanding state transitions and exploring swap combinations.
Iterative Approach with TabulationO(n^2)O(n)Preferred when avoiding recursion and computing mismatch counts iteratively.

Frequently asked questions

Is Transform to Chessboard easy or hard?

Transform to Chessboard is classified as a hard problem because the challenge lies in recognizing the structural constraints of a valid chessboard. Once the row and column pattern rules are understood, the implementation becomes straightforward but still requires careful counting logic.

Transform to Chessboard Python/Java solution

Python and Java implementations typically iterate through rows and columns, verify complementary patterns, and count mismatches relative to alternating parity positions. Both languages achieve O(n^2) time complexity using simple loops and counters.

How to solve Transform to Chessboard in O(n^2)?

Iterate through the matrix and verify that every row is either identical to the first row or its inverse. Do the same for columns. Then count mismatches against the expected alternating pattern and compute the minimal swaps needed for rows and columns separately.

What is the best approach for Transform to Chessboard?

The most efficient approach is pattern matching with position swapping. It checks whether rows and columns follow two complementary patterns and then counts the minimal swaps needed to match a valid chessboard arrangement. The algorithm runs in O(n^2) time and O(1) space.

Is Transform to Chessboard asked at Google/Amazon/Meta?

Chessboard transformation and matrix parity problems appear in interviews at companies like Google, Amazon, and Meta because they test reasoning about patterns, invariants, and matrix manipulation. Variants often involve validating grid structures or minimizing swaps.

What data structure is used in Transform to Chessboard?

The primary structure is a 2D matrix or array. Efficient implementations also use bit manipulation to represent rows or columns as bit masks, making it easier to compare patterns and detect inversions.

What is the time complexity of Transform to Chessboard?

The optimal solution runs in O(n^2) time because every cell in the matrix must be inspected to validate row and column patterns. Space complexity can be O(1) if calculations are performed directly on the matrix without auxiliary structures.

Comments

Now write it yourselfClose this page and solve Transform to Chessboard in the editor, without looking.
Practise Transform to Chessboard