You are given a 2D matrix mat
with m
rows and n
columns, as well as two integers r
and c
representing the desired number of rows and columns for a new reshaped matrix.
Your task is to reshape mat
into a new matrix with r
rows and c
columns, containing all the elements of mat
in the same row-traversing order (left to right, top to bottom).
If the reshape operation with the given r
and c
is not possible (i.e., the total number of elements does not match), return mat
as is.
mat
(2D list/array), r
(int), c
(int)r
x c
with the same elements in row-wise order, or original mat
if impossible.
Let's break down the problem step by step. First, we need to determine if reshaping is possible. The only way to reshape a matrix without losing or duplicating elements is if the total number of elements stays the same. So, m * n
must equal r * c
.
If reshaping is possible, we need to copy the elements from the original matrix into the new matrix, making sure they appear in the same order as they were traversed row-wise. We can think of "flattening" the original matrix into a single list, then filling up the new matrix row by row from this list.
A naive (brute-force) approach would be to flatten the matrix into a list, then fill the new matrix. But we can optimize this by calculating the mapping from the old position to the new one directly using indices, saving space and time.
In summary, the main challenges are:
mat
to the new shapeLet's walk through the algorithm step by step:
m
) and columns (n
) in the original matrix. Compute the total number of elements (m * n
).
m * n != r * c
, return mat
as is.
r
x c
, filled with zeroes or placeholders.
m * n
), compute:
mat
at mat[i // n][i % n]
reshaped[i // c][i % c]
This approach avoids extra space for flattening and is efficient. We use integer division and modulo to map 1D indices to 2D positions.
Let's use the following example:
mat = [[1, 2], [3, 4]]
r = 1
, c = 4
Step 1: The original matrix has 2 rows and 2 columns (2 * 2 = 4
elements). The target is 1 row and 4 columns (1 * 4 = 4
). Reshape is possible.
Step 2: Flatten the original matrix in row-wise order: [1, 2, 3, 4].
Step 3: Fill the new matrix:
i = 0:
mat[0][0]
(1) → reshaped[0][0]
i = 1:
mat[0][1]
(2) → reshaped[0][1]
i = 2:
mat[1][0]
(3) → reshaped[0][2]
i = 3:
mat[1][1]
(4) → reshaped[0][3]
Result: [[1, 2, 3, 4]]
If r = 2
, c = 4
, reshape is not possible, so return the original matrix.
Brute-force approach:
Optimized approach (direct mapping):
The time complexity is optimal, since every element must be visited at least once.
The key to solving the "Reshape the Matrix" problem is recognizing that reshaping is only possible if the total number of elements stays the same. By using index mapping (via division and modulo), we can efficiently move each element from its old position to its new one without extra space for flattening. This approach is both elegant and efficient, preserving the original order and meeting all constraints.
class Solution:
def matrixReshape(self, mat, r, c):
m, n = len(mat), len(mat[0])
if m * n != r * c:
return mat
reshaped = [[0 for _ in range(c)] for _ in range(r)]
for i in range(m * n):
reshaped[i // c][i % c] = mat[i // n][i % n]
return reshaped
class Solution {
public:
vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) {
int m = mat.size(), n = mat[0].size();
if (m * n != r * c) return mat;
vector<vector<int>> reshaped(r, vector<int>(c));
for (int i = 0; i < m * n; ++i) {
reshaped[i / c][i % c] = mat[i / n][i % n];
}
return reshaped;
}
};
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
int m = mat.length, n = mat[0].length;
if (m * n != r * c) return mat;
int[][] reshaped = new int[r][c];
for (int i = 0; i < m * n; i++) {
reshaped[i / c][i % c] = mat[i / n][i % n];
}
return reshaped;
}
}
var matrixReshape = function(mat, r, c) {
let m = mat.length, n = mat[0].length;
if (m * n !== r * c) return mat;
let reshaped = Array.from({length: r}, () => Array(c));
for (let i = 0; i < m * n; i++) {
reshaped[Math.floor(i / c)][i % c] = mat[Math.floor(i / n)][i % n];
}
return reshaped;
};