Facebook Pixel

1886. Determine Whether Matrix Can Be Obtained By Rotation

Problem Description

You are given two square binary matrices of the same size: mat and target. Each matrix is n x n in size and contains only 0s and 1s.

Your task is to determine if you can transform mat to exactly match target by rotating mat in 90-degree increments. You can rotate the matrix 0, 1, 2, or 3 times (where 0 rotations means no change, and each rotation is 90 degrees clockwise).

The function should return true if mat can be made equal to target through rotation, and false otherwise.

For example, if you have a 2x2 matrix:

[[0,1],
 [1,0]]

After a 90-degree clockwise rotation, it becomes:

[[1,0],
 [0,1]]

The solution works by:

  1. Checking if mat already equals target (0 rotations)
  2. Rotating mat by 90 degrees and checking again
  3. Repeating this process up to 4 times total (since 4 rotations of 90 degrees returns to the original position)

The rotation algorithm used in the code performs an in-place rotation by swapping elements in cycles around the matrix. For each layer of the matrix (working from outside to inside), it rotates four elements at a time in a circular pattern.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that rotating a matrix by 90 degrees clockwise exactly 4 times brings it back to its original position. This creates a cycle: original → 90° → 180° → 270° → 360° (back to original).

Since we want to check if mat can become target through rotation, we only need to check at most 4 positions:

  • The original position (0 rotations)
  • After 90° rotation (1 rotation)
  • After 180° rotation (2 rotations)
  • After 270° rotation (3 rotations)

If target matches mat at any of these 4 positions, then we can transform mat into target.

The approach becomes straightforward: keep rotating mat and checking if it equals target after each rotation. If we find a match within 4 rotations, return true. If we've checked all 4 possible orientations without finding a match, return false.

For the rotation itself, we can perform it in-place to save space. The rotation works by moving elements in groups of 4 around the matrix. For a 90-degree clockwise rotation:

  • Top row elements move to the right column
  • Right column elements move to the bottom row (reversed)
  • Bottom row elements move to the left column
  • Left column elements move to the top row (reversed)

This cycle of 4 swaps is performed for each "layer" of the matrix, working from the outermost layer inward. The formula matrix[i][j] → matrix[j][n-1-i] captures this transformation mathematically.

Solution Approach

The solution implements a straightforward approach with two main components: a rotation function and a checking loop.

Main Logic: The solution tries all 4 possible rotations of mat and checks if any of them match target:

for _ in range(4):
    if mat == target:
        return True
    rotate(mat)
return False

This loop runs exactly 4 times because after 4 rotations of 90 degrees, we're back to the original matrix. If no match is found after checking all 4 orientations, we return false.

In-Place Rotation Algorithm: The rotate function performs a 90-degree clockwise rotation in-place using a layer-by-layer approach:

def rotate(matrix):
    n = len(matrix)
    for i in range(n // 2):
        for j in range(i, n - 1 - i):
            # Perform 4-way swap

The rotation works by processing the matrix in concentric square layers from outside to inside:

  • i represents the current layer (0 for outermost, 1 for next inner layer, etc.)
  • We only need to process n // 2 layers
  • For each layer, we iterate through elements from position i to n - 1 - i

Four-Way Element Swap: For each element in a layer, we perform a cyclic swap of 4 elements:

t = matrix[i][j]                                    # Save top element
matrix[i][j] = matrix[n - j - 1][i]                # Left → Top
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1]  # Bottom → Left  
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1]  # Right → Bottom
matrix[j][n - i - 1] = t                            # Top → Right

The indices follow the pattern for 90-degree clockwise rotation:

  • (i, j)(j, n-1-i)(n-1-i, n-1-j)(n-1-j, i) → back to (i, j)

Time and Space Complexity:

  • Time: O(n²) for each rotation × 4 rotations = O(n²)
  • Space: O(1) as the rotation is done in-place

The elegance of this solution lies in its simplicity - rather than computing all rotations separately or using complex mathematical transformations, it simply rotates and checks, leveraging the fact that there are only 4 possible orientations to consider.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example to illustrate how the solution works.

Given:

  • mat = [[0,1],[1,0]]
  • target = [[1,0],[0,1]]

Step 1: Check original matrix (0 rotations)

mat:     [[0,1],     target: [[1,0],
          [1,0]]              [0,1]]

Compare: mat ≠ target, so continue.

Step 2: Rotate mat by 90° clockwise

The rotation process for this 2×2 matrix:

  • We have 1 layer (since n//2 = 2//2 = 1)
  • For layer 0, we process element at position (0,0)
  • Perform 4-way swap:
    • Save top: temp = mat[0][0] = 0
    • Left → Top: mat[0][0] = mat[1][0] = 1
    • Bottom → Left: mat[1][0] = mat[1][1] = 0
    • Right → Bottom: mat[1][1] = mat[0][1] = 1
    • Top → Right: mat[0][1] = temp = 0

After rotation:

mat:     [[1,0],     target: [[1,0],
          [0,1]]              [0,1]]

Compare: mat == target ✓ Return true!

Let's trace another example where we need more rotations:

Given:

  • mat = [[1,1],[0,1]]
  • target = [[1,0],[1,1]]

Iteration 1 (0 rotations):

mat:     [[1,1],     target: [[1,0],
          [0,1]]              [1,1]]

Not equal, rotate.

Iteration 2 (90° rotation): After rotating mat:

mat:     [[0,1],     target: [[1,0],
          [1,1]]              [1,1]]

Not equal, rotate again.

Iteration 3 (180° total rotation): After rotating mat:

mat:     [[1,0],     target: [[1,0],
          [1,1]]              [1,1]]

Compare: mat == target ✓ Return true!

The algorithm found that after 2 rotations (180°), mat matches target.

For a case that returns false, consider:

  • mat = [[1,1],[1,1]]
  • target = [[0,0],[0,0]]

No matter how many times we rotate a matrix of all 1s, it will never match a matrix of all 0s. After checking all 4 orientations, the algorithm returns false.

Solution Implementation

1class Solution:
2    def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
3        """
4        Determines if matrix 'mat' can be rotated (0, 90, 180, or 270 degrees) to match 'target'.
5      
6        Args:
7            mat: Source matrix to rotate
8            target: Target matrix to match
9          
10        Returns:
11            True if mat can be rotated to match target, False otherwise
12        """
13      
14        def rotate_90_clockwise(matrix: List[List[int]]) -> None:
15            """
16            Rotates the matrix 90 degrees clockwise in-place using a layer-by-layer approach.
17          
18            Args:
19                matrix: Square matrix to rotate in-place
20            """
21            n = len(matrix)
22          
23            # Process the matrix layer by layer from outside to inside
24            for layer in range(n // 2):
25                # Define the boundaries of the current layer
26                first = layer
27                last = n - 1 - layer
28              
29                # Rotate elements in the current layer
30                for i in range(first, last):
31                    # Calculate offset from the start of the layer
32                    offset = i - first
33                  
34                    # Save top element
35                    temp = matrix[first][i]
36                  
37                    # Move left to top
38                    matrix[first][i] = matrix[last - offset][first]
39                  
40                    # Move bottom to left
41                    matrix[last - offset][first] = matrix[last][last - offset]
42                  
43                    # Move right to bottom
44                    matrix[last][last - offset] = matrix[i][last]
45                  
46                    # Move top (saved) to right
47                    matrix[i][last] = temp
48      
49        # Check all four possible rotations (0°, 90°, 180°, 270°)
50        for rotation_count in range(4):
51            # Check if current orientation matches target
52            if mat == target:
53                return True
54          
55            # Rotate matrix 90 degrees clockwise for next check
56            rotate_90_clockwise(mat)
57      
58        # No rotation matched the target
59        return False
60
1class Solution {
2    /**
3     * Determines if matrix 'mat' can be rotated (0, 90, 180, or 270 degrees clockwise)
4     * to match the 'target' matrix.
5     * 
6     * @param mat The source matrix to rotate
7     * @param target The target matrix to match
8     * @return true if mat can be rotated to match target, false otherwise
9     */
10    public boolean findRotation(int[][] mat, int[][] target) {
11        // Check all 4 possible rotations (0°, 90°, 180°, 270°)
12        int rotationAttempts = 4;
13      
14        while (rotationAttempts-- > 0) {
15            // Check if current rotation matches target
16            if (equals(mat, target)) {
17                return true;
18            }
19            // Rotate matrix 90 degrees clockwise for next check
20            rotate(mat);
21        }
22      
23        return false;
24    }
25
26    /**
27     * Rotates the given square matrix 90 degrees clockwise in-place.
28     * Uses a layer-by-layer approach from outside to inside.
29     * 
30     * @param matrix The matrix to rotate
31     */
32    private void rotate(int[][] matrix) {
33        int n = matrix.length;
34      
35        // Process each layer from outer to inner
36        for (int layer = 0; layer < n / 2; ++layer) {
37            // Define the boundaries of current layer
38            int first = layer;
39            int last = n - 1 - layer;
40          
41            // Rotate elements in current layer
42            for (int offset = first; offset < last; ++offset) {
43                // Save top element
44                int temp = matrix[first][offset];
45              
46                // Move left to top
47                matrix[first][offset] = matrix[n - offset - 1][first];
48              
49                // Move bottom to left
50                matrix[n - offset - 1][first] = matrix[last][n - offset - 1];
51              
52                // Move right to bottom
53                matrix[last][n - offset - 1] = matrix[offset][last];
54              
55                // Move saved top to right
56                matrix[offset][last] = temp;
57            }
58        }
59    }
60
61    /**
62     * Checks if two matrices are identical.
63     * 
64     * @param matrix1 The first matrix
65     * @param matrix2 The second matrix
66     * @return true if matrices are identical, false otherwise
67     */
68    private boolean equals(int[][] matrix1, int[][] matrix2) {
69        int n = matrix1.length;
70      
71        // Compare each element
72        for (int row = 0; row < n; ++row) {
73            for (int col = 0; col < n; ++col) {
74                if (matrix1[row][col] != matrix2[row][col]) {
75                    return false;
76                }
77            }
78        }
79      
80        return true;
81    }
82}
83
1class Solution {
2public:
3    bool findRotation(vector<vector<int>>& mat, vector<vector<int>>& target) {
4        int n = mat.size();
5      
6        // Try all 4 possible rotations (0°, 90°, 180°, 270°)
7        for (int rotationCount = 0; rotationCount < 4; ++rotationCount) {
8            // Create a new matrix to store the rotated result
9            vector<vector<int>> rotatedMatrix(n, vector<int>(n));
10          
11            // Perform 90-degree clockwise rotation
12            // For element at position (i, j) in original matrix,
13            // it moves to position (j, n-1-i) after rotation
14            for (int row = 0; row < n; ++row) {
15                for (int col = 0; col < n; ++col) {
16                    rotatedMatrix[row][col] = mat[col][n - row - 1];
17                }
18            }
19          
20            // Check if the rotated matrix matches the target
21            if (rotatedMatrix == target) {
22                return true;
23            }
24          
25            // Update mat for the next rotation iteration
26            mat = rotatedMatrix;
27        }
28      
29        // No rotation matched the target
30        return false;
31    }
32};
33
1/**
2 * Determines if matrix can be rotated (0°, 90°, 180°, or 270°) to match target matrix
3 * @param mat - The source matrix to rotate
4 * @param target - The target matrix to match
5 * @returns true if mat can be rotated to match target, false otherwise
6 */
7function findRotation(mat: number[][], target: number[][]): boolean {
8    // Try all 4 possible rotations (0°, 90°, 180°, 270°)
9    for (let rotationCount = 0; rotationCount < 4; rotationCount++) {
10        rotate(mat);
11      
12        // Check if current rotation matches target
13        if (isEqual(mat, target)) {
14            return true;
15        }
16    }
17  
18    return false;
19}
20
21/**
22 * Checks if two matrices are identical
23 * @param matrixA - First matrix to compare
24 * @param matrixB - Second matrix to compare
25 * @returns true if matrices are identical, false otherwise
26 */
27function isEqual(matrixA: number[][], matrixB: number[][]): boolean {
28    const size = matrixA.length;
29  
30    // Compare each element
31    for (let row = 0; row < size; row++) {
32        for (let col = 0; col < size; col++) {
33            if (matrixA[row][col] !== matrixB[row][col]) {
34                return false;
35            }
36        }
37    }
38  
39    return true;
40}
41
42/**
43 * Rotates a square matrix 90 degrees clockwise in-place
44 * Uses a four-way swap to rotate elements in groups of 4
45 * @param matrix - The matrix to rotate (modified in-place)
46 */
47function rotate(matrix: number[][]): void {
48    const size = matrix.length;
49  
50    // Process matrix in layers from outside to inside
51    // Only need to process half the rows (rounded down)
52    for (let row = 0; row < size >> 1; row++) {
53        // Process half the columns (rounded up for odd-sized matrices)
54        for (let col = 0; col < (size + 1) >> 1; col++) {
55            // Perform 4-way swap for 90-degree rotation
56            // Each element moves to its clockwise position
57            [
58                matrix[row][col],                           // Top-left
59                matrix[size - 1 - col][row],               // Bottom-left
60                matrix[size - 1 - row][size - 1 - col],    // Bottom-right
61                matrix[col][size - 1 - row]                // Top-right
62            ] = [
63                matrix[size - 1 - col][row],               // Bottom-left → Top-left
64                matrix[size - 1 - row][size - 1 - col],    // Bottom-right → Bottom-left
65                matrix[col][size - 1 - row],               // Top-right → Bottom-right
66                matrix[row][col]                           // Top-left → Top-right
67            ];
68        }
69    }
70}
71

Time and Space Complexity

Time Complexity: O(n²)

The algorithm performs at most 4 rotations, and each rotation operation takes O(n²) time where n is the dimension of the square matrix.

Breaking down the rotation function:

  • The outer loop runs n/2 times (iterating through layers)
  • The inner loop runs approximately n - 2i times for each layer i
  • The total number of elements processed is n²/4 (since we process each element exactly once in a 90-degree rotation)
  • Each element swap operation takes O(1) time

The comparison mat == target takes O(n²) time as it needs to compare all elements.

Since we perform at most 4 rotations and 4 comparisons, the total time complexity is 4 * O(n²) + 4 * O(n²) = O(n²).

Space Complexity: O(1)

The algorithm modifies the matrix in-place without using any additional data structures that scale with input size. Only a constant amount of extra space is used:

  • The temporary variable t for swapping elements
  • Loop counters i and j
  • The variable n storing the matrix dimension

Therefore, the space complexity is O(1) (constant space).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Modifying the Original Matrix

The most significant pitfall in this solution is that it modifies the input matrix mat in-place during rotation. After the function executes, mat will be left in a rotated state (potentially rotated up to 270 degrees), which can cause unexpected behavior if the caller expects the original matrix to remain unchanged.

Example of the problem:

mat = [[0,1],[1,0]]
target = [[1,0],[0,1]]
solution = Solution()
result = solution.findRotation(mat, target)
print(mat)  # mat is now modified - could be [[1,0],[0,1]] instead of original

Solution: Create a deep copy of the matrix before performing rotations:

def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
    # Create a deep copy to avoid modifying the original
    mat_copy = [row[:] for row in mat]
  
    for _ in range(4):
        if mat_copy == target:
            return True
        rotate_90_clockwise(mat_copy)
    return False

2. Inefficient Comparison After Unnecessary Rotations

The current implementation always rotates the matrix even after the last comparison. If no match is found after checking all 4 orientations, the matrix gets rotated a 4th time unnecessarily (returning it to the original orientation, but still performing unnecessary work).

Solution: Check before rotating on the last iteration:

for i in range(4):
    if mat == target:
        return True
    if i < 3:  # Don't rotate after the last check
        rotate_90_clockwise(mat)
return False

3. Alternative Mathematical Approach Overlooked

While the in-place rotation is space-efficient, for read-only operations or when preserving the original matrix is important, you could use index mapping without modifying the matrix:

Solution using index transformation:

def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
    n = len(mat)
  
    # Check original orientation
    if mat == target:
        return True
  
    # Check 90-degree rotation
    if all(mat[n-1-j][i] == target[i][j] for i in range(n) for j in range(n)):
        return True
  
    # Check 180-degree rotation
    if all(mat[n-1-i][n-1-j] == target[i][j] for i in range(n) for j in range(n)):
        return True
  
    # Check 270-degree rotation
    if all(mat[j][n-1-i] == target[i][j] for i in range(n) for j in range(n)):
        return True
  
    return False

This approach avoids matrix modification entirely and can be more efficient for large matrices since it can short-circuit as soon as a mismatch is found.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using input 56?

1KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12def letter_combinations_of_phone_number(digits):
13    def dfs(path, res):
14        if len(path) == len(digits):
15            res.append(''.join(path))
16            return
17
18        next_number = digits[len(path)]
19        for letter in KEYBOARD[next_number]:
20            path.append(letter)
21            dfs(path, res)
22            path.pop()
23
24    res = []
25    dfs([], res)
26    return res
27
1private static final Map<Character, char[]> KEYBOARD = Map.of(
2    '2', "abc".toCharArray(),
3    '3', "def".toCharArray(),
4    '4', "ghi".toCharArray(),
5    '5', "jkl".toCharArray(),
6    '6', "mno".toCharArray(),
7    '7', "pqrs".toCharArray(),
8    '8', "tuv".toCharArray(),
9    '9', "wxyz".toCharArray()
10);
11
12public static List<String> letterCombinationsOfPhoneNumber(String digits) {
13    List<String> res = new ArrayList<>();
14    dfs(new StringBuilder(), res, digits.toCharArray());
15    return res;
16}
17
18private static void dfs(StringBuilder path, List<String> res, char[] digits) {
19    if (path.length() == digits.length) {
20        res.add(path.toString());
21        return;
22    }
23    char next_digit = digits[path.length()];
24    for (char letter : KEYBOARD.get(next_digit)) {
25        path.append(letter);
26        dfs(path, res, digits);
27        path.deleteCharAt(path.length() - 1);
28    }
29}
30
1const KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12function letter_combinations_of_phone_number(digits) {
13    let res = [];
14    dfs(digits, [], res);
15    return res;
16}
17
18function dfs(digits, path, res) {
19    if (path.length === digits.length) {
20        res.push(path.join(''));
21        return;
22    }
23    let next_number = digits.charAt(path.length);
24    for (let letter of KEYBOARD[next_number]) {
25        path.push(letter);
26        dfs(digits, path, res);
27        path.pop();
28    }
29}
30

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More