Facebook Pixel

566. Reshape the Matrix

EasyArrayMatrixSimulation
Leetcode Link

Problem Description

You need to implement a function that reshapes a matrix, similar to MATLAB's reshape function. Given an m x n matrix mat and two integers r and c, you should reshape the matrix into a new matrix with r rows and c columns.

The reshaping process should follow these rules:

  1. Element Order Preservation: All elements from the original matrix should be read in row-traversing order (left to right, top to bottom) and placed into the new matrix in the same row-traversing order.

  2. Validity Check: The reshape operation is only valid if the total number of elements remains the same. That means m * n must equal r * c. If this condition is not met, return the original matrix unchanged.

  3. Output: If reshaping is possible, return the new reshaped matrix with dimensions r x c. Otherwise, return the original matrix.

For example, if you have a 2x2 matrix [[1,2],[3,4]] and want to reshape it to 1x4, the elements would be read as 1, 2, 3, 4 and placed into the new matrix as [[1,2,3,4]].

The solution uses index mapping to efficiently transfer elements from the original matrix to the reshaped matrix. For any linear index i (from 0 to m*n-1), the element at position [i // n][i % n] in the original matrix is placed at position [i // c][i % c] in the new matrix.

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

Intuition

The key insight is that reshaping a matrix is essentially about reinterpreting how we group the same sequence of elements. When we read a 2D matrix in row-major order, we get a linear sequence of elements. This same sequence can then be regrouped into different dimensions.

Think of the matrix elements as beads on a string. When we flatten a 2D matrix by reading row by row, we get all elements in a single line. Now we can take this same string of beads and arrange them into a new rectangular pattern with different dimensions.

The mathematical trick here is using index conversion. Any element in a 2D matrix can be mapped to a unique position in a 1D array and vice versa. For a matrix with n columns:

  • A 2D position (row, col) maps to 1D index: row * n + col
  • A 1D index i maps back to 2D: row = i // n, col = i % n

Since we're transforming from one 2D shape to another, we can use a single loop counter i from 0 to m*n-1 to represent the position in the flattened sequence. Then:

  • To read from the original matrix with n columns: position is [i // n][i % n]
  • To write to the new matrix with c columns: position is [i // c][i % c]

This avoids explicitly flattening the matrix into a 1D array and then reshaping it, making the solution more efficient with direct element-to-element mapping.

The prerequisite check m * n != r * c ensures we have the exact same number of elements to work with - you can't create more elements or lose elements during reshaping, just rearrange them.

Solution Approach

The implementation follows a simulation approach where we directly map elements from the original matrix to their new positions in the reshaped matrix.

Step 1: Validate the Reshape Operation

First, we extract the dimensions of the original matrix:

  • m = len(mat) - number of rows
  • n = len(mat[0]) - number of columns

Then we check if reshaping is valid by comparing the total number of elements:

if m * n != r * c:
    return mat

If the total elements don't match, we cannot reshape and return the original matrix.

Step 2: Create the Result Matrix

We initialize a new matrix with the desired dimensions:

ans = [[0] * c for _ in range(r)]

This creates r rows, each containing c columns, all initialized to 0.

Step 3: Transfer Elements Using Index Mapping

The core of the algorithm uses a single loop to iterate through all m * n elements:

for i in range(m * n):
    ans[i // c][i % c] = mat[i // n][i % n]

For each linear index i:

  • Reading from original matrix: The position [i // n][i % n] gives us the element at the i-th position when reading the original matrix in row-major order

    • i // n gives the row index (how many complete rows of size n we've passed)
    • i % n gives the column index (position within the current row)
  • Writing to new matrix: The position [i // c][i % c] determines where this element should go in the reshaped matrix

    • i // c gives the row index in the new matrix (how many complete rows of size c we've filled)
    • i % c gives the column index in the new matrix (position within the current row)

Step 4: Return the Result

After all elements have been transferred, we return the reshaped matrix ans.

The time complexity is O(m * n) as we visit each element exactly once. The space complexity is O(r * c) for the new matrix, which equals O(m * n) since r * c = m * n for valid reshapes.

Ready to land your dream job?

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

Start Evaluator

Example Walkthrough

Let's walk through reshaping a 2×3 matrix into a 3×2 matrix.

Given:

  • Original matrix mat = [[1,2,3],[4,5,6]] with dimensions m=2, n=3
  • Target dimensions: r=3, c=2

Step 1: Validate

  • Total elements in original: 2 × 3 = 6
  • Total elements in target: 3 × 2 = 6
  • Since they match, reshaping is valid ✓

Step 2: Create result matrix

ans = [[0,0],
       [0,0],
       [0,0]]

Step 3: Transfer elements using index mapping

For each linear index i from 0 to 5:

  • i = 0:

    • Read from mat[0//3][0%3] = mat[0][0] = 1
    • Write to ans[0//2][0%2] = ans[0][0]
    • Result: ans[0][0] = 1
  • i = 1:

    • Read from mat[1//3][1%3] = mat[0][1] = 2
    • Write to ans[1//2][1%2] = ans[0][1]
    • Result: ans[0][1] = 2
  • i = 2:

    • Read from mat[2//3][2%3] = mat[0][2] = 3
    • Write to ans[2//2][2%2] = ans[1][0]
    • Result: ans[1][0] = 3
  • i = 3:

    • Read from mat[3//3][3%3] = mat[1][0] = 4
    • Write to ans[3//2][3%2] = ans[1][1]
    • Result: ans[1][1] = 4
  • i = 4:

    • Read from mat[4//3][4%3] = mat[1][1] = 5
    • Write to ans[4//2][4%2] = ans[2][0]
    • Result: ans[2][0] = 5
  • i = 5:

    • Read from mat[5//3][5%3] = mat[1][2] = 6
    • Write to ans[5//2][5%2] = ans[2][1]
    • Result: ans[2][1] = 6

Final Result:

ans = [[1,2],
       [3,4],
       [5,6]]

The elements 1,2,3,4,5,6 were read in row-major order from the original 2×3 matrix and placed into the new 3×2 matrix maintaining the same sequential order.

Solution Implementation

1class Solution:
2    def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
3        # Get dimensions of the original matrix
4        rows, cols = len(mat), len(mat[0])
5      
6        # Check if reshape is possible (total elements must match)
7        if rows * cols != r * c:
8            return mat
9      
10        # Initialize the reshaped matrix with zeros
11        reshaped_matrix = [[0] * c for _ in range(r)]
12      
13        # Iterate through all elements using a single index
14        for index in range(rows * cols):
15            # Calculate source position in original matrix
16            source_row = index // cols
17            source_col = index % cols
18          
19            # Calculate target position in reshaped matrix
20            target_row = index // c
21            target_col = index % c
22          
23            # Copy element from source to target position
24            reshaped_matrix[target_row][target_col] = mat[source_row][source_col]
25      
26        return reshaped_matrix
27
1class Solution {
2    /**
3     * Reshapes a matrix to new dimensions if possible.
4     * @param mat The original matrix to reshape
5     * @param r The target number of rows
6     * @param c The target number of columns
7     * @return The reshaped matrix if possible, otherwise the original matrix
8     */
9    public int[][] matrixReshape(int[][] mat, int r, int c) {
10        // Get dimensions of the original matrix
11        int originalRows = mat.length;
12        int originalCols = mat[0].length;
13      
14        // Check if reshape is possible (total elements must be equal)
15        if (originalRows * originalCols != r * c) {
16            return mat;
17        }
18      
19        // Create the result matrix with new dimensions
20        int[][] reshapedMatrix = new int[r][c];
21      
22        // Iterate through all elements and map them to new positions
23        int totalElements = originalRows * originalCols;
24        for (int index = 0; index < totalElements; index++) {
25            // Calculate source position in original matrix
26            int sourceRow = index / originalCols;
27            int sourceCol = index % originalCols;
28          
29            // Calculate target position in reshaped matrix
30            int targetRow = index / c;
31            int targetCol = index % c;
32          
33            // Copy element from source to target position
34            reshapedMatrix[targetRow][targetCol] = mat[sourceRow][sourceCol];
35        }
36      
37        return reshapedMatrix;
38    }
39}
40
1class Solution {
2public:
3    vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) {
4        // Get the dimensions of the original matrix
5        int originalRows = mat.size();
6        int originalCols = mat[0].size();
7      
8        // Check if reshape is possible - total elements must be the same
9        if (originalRows * originalCols != r * c) {
10            return mat;  // Return original matrix if reshape is not possible
11        }
12      
13        // Create the reshaped matrix with new dimensions
14        vector<vector<int>> reshapedMatrix(r, vector<int>(c));
15      
16        // Iterate through all elements using a single loop
17        // Map each element from original matrix to new matrix
18        for (int flatIndex = 0; flatIndex < originalRows * originalCols; ++flatIndex) {
19            // Calculate position in original matrix
20            int sourceRow = flatIndex / originalCols;
21            int sourceCol = flatIndex % originalCols;
22          
23            // Calculate position in reshaped matrix
24            int targetRow = flatIndex / c;
25            int targetCol = flatIndex % c;
26          
27            // Copy element from original position to new position
28            reshapedMatrix[targetRow][targetCol] = mat[sourceRow][sourceCol];
29        }
30      
31        return reshapedMatrix;
32    }
33};
34
1/**
2 * Reshapes a matrix from its original dimensions to new dimensions with r rows and c columns.
3 * The reshaping is done by reading elements row by row from the original matrix
4 * and filling the new matrix row by row.
5 * 
6 * @param mat - The original 2D matrix to be reshaped
7 * @param r - The number of rows in the reshaped matrix
8 * @param c - The number of columns in the reshaped matrix
9 * @returns The reshaped matrix if possible, otherwise returns the original matrix
10 */
11function matrixReshape(mat: number[][], r: number, c: number): number[][] {
12    // Get dimensions of the original matrix
13    const originalRows: number = mat.length;
14    const originalCols: number = mat[0].length;
15  
16    // Check if reshape is possible - total elements must match
17    if (originalRows * originalCols !== r * c) {
18        return mat;
19    }
20  
21    // Initialize the result matrix with the new dimensions
22    const reshapedMatrix: number[][] = Array.from(
23        { length: r }, 
24        () => new Array<number>(c).fill(0)
25    );
26  
27    // Linear index to track position in the reshaped matrix
28    let linearIndex: number = 0;
29  
30    // Iterate through the original matrix row by row
31    for (let row: number = 0; row < originalRows; row++) {
32        for (let col: number = 0; col < originalCols; col++) {
33            // Calculate the new position in the reshaped matrix
34            // Math.floor(linearIndex / c) gives the row index
35            // linearIndex % c gives the column index
36            const newRow: number = Math.floor(linearIndex / c);
37            const newCol: number = linearIndex % c;
38          
39            // Copy the element to the new position
40            reshapedMatrix[newRow][newCol] = mat[row][col];
41          
42            // Move to the next linear position
43            linearIndex++;
44        }
45    }
46  
47    return reshapedMatrix;
48}
49

Time and Space Complexity

The time complexity is O(m × n), where m and n are the number of rows and columns of the original matrix, respectively. This is because the algorithm iterates through all m × n elements exactly once in the for loop, performing constant-time operations for each element (calculating indices and assigning values).

The space complexity is O(r × c) for the output matrix ans. However, if we exclude the space required for the output (as it's necessary for returning the result), the space complexity is O(1). This means the algorithm uses only a constant amount of extra space beyond the input and output, with just a few variables (m, n, i) that don't scale with the input size.

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

Common Pitfalls

1. Incorrect Index Calculation for Source Matrix

A frequent mistake is using the wrong divisor when calculating the source indices. Developers often mistakenly use the target dimensions instead of the source dimensions:

Wrong:

# Using 'c' (target columns) instead of 'cols' (source columns)
source_row = index // c  # Incorrect!
source_col = index % c   # Incorrect!

Correct:

source_row = index // cols  # Use original column count
source_col = index % cols   # Use original column count

This error occurs because it's easy to confuse which dimension belongs to which matrix when working with multiple coordinate systems simultaneously.

2. Empty Matrix Handling

The code assumes mat[0] exists to get the column count. If an empty matrix is passed, this will cause an IndexError:

Problem:

cols = len(mat[0])  # Fails if mat is empty []

Solution:

if not mat or not mat[0]:
    return mat
rows, cols = len(mat), len(mat[0])

3. Using Wrong Variables in the Loop

When using the compact one-liner approach, it's easy to mix up the variables:

Wrong:

# Swapping n and c in the denominators
ans[i // n][i % n] = mat[i // c][i % c]  # Variables are swapped!

Correct:

ans[i // c][i % c] = mat[i // n][i % n]  # n for source, c for target

4. Modifying the Original Matrix

Some developers try to optimize space by reusing the original matrix when dimensions match:

Problematic approach:

if r == rows:  # Same number of rows
    return mat  # Wrong! Columns might be different

Even if the row count matches, the column structure needs to change unless both dimensions match exactly.

5. Integer Division Confusion in Different Languages

If translating this solution to other languages, be aware that division operators behave differently:

Python 2 vs Python 3:

# Python 2: / performs integer division for integers
# Python 3: // is needed for integer division
index // cols  # Correct for Python 3

In languages like JavaScript:

// Wrong: JavaScript uses floating-point division
Math.floor(index / cols)  // Need explicit floor operation

The safest approach is to always use explicit integer division or floor operations to ensure consistent behavior across different environments.

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

Depth first search is equivalent to which of the tree traversal order?


Recommended Readings

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

Load More