2022. Convert 1D Array Into 2D Array
Problem Description
You are given a 1-dimensional array called original
and two integers m
and n
. Your task is to reshape this 1D array into a 2D array with m
rows and n
columns.
The reshaping should follow these rules:
- Elements at indices
0
ton-1
fromoriginal
should form the first row - Elements at indices
n
to2*n-1
should form the second row - Elements at indices
2*n
to3*n-1
should form the third row - This pattern continues until all elements are placed
The transformation is only possible if the total number of elements in original
equals m * n
. If this condition is not met, return an empty 2D array.
For example, if original = [1,2,3,4]
, m = 2
, and n = 2
:
- First row: elements at indices 0-1 →
[1,2]
- Second row: elements at indices 2-3 →
[3,4]
- Result:
[[1,2],[3,4]]
The solution checks if m * n
equals the length of original
. If not, it returns an empty array. Otherwise, it uses list comprehension to slice the original array into chunks of size n
, creating each row of the 2D array by taking elements from index i
to i+n
for each starting position i
that is a multiple of n
.
Intuition
The key insight is recognizing this as a reshape operation where we're taking a linear sequence and arranging it into a grid format. Think of it like arranging a single line of people into rows for a group photo.
First, we need to verify if the reshape is even possible. Since we need to use all elements from the original array to fill an m × n
grid completely, the total number of elements must match exactly. This gives us our validation condition: m * n == len(original)
.
Once we know the reshape is valid, the transformation becomes straightforward. We need to take consecutive chunks of n
elements from the original array to form each row. Why chunks of size n
? Because each row in our target 2D array has exactly n
columns.
The pattern emerges clearly:
- Row 0: elements from index
0
ton-1
- Row 1: elements from index
n
to2n-1
- Row 2: elements from index
2n
to3n-1
- Row i: elements from index
i*n
to(i+1)*n-1
This naturally leads to a slicing approach where we iterate through the original array in steps of n
, taking n
elements at each step. Python's list slicing original[i:i+n]
perfectly captures this chunk extraction, and we can generate all rows using a list comprehension that starts at indices 0, n, 2n, ...
up to m*n
.
The elegance of this solution lies in recognizing that reshaping is simply a matter of reinterpreting the same data with different indexing boundaries, without any complex transformations needed.
Solution Approach
The implementation follows a simulation approach where we directly construct the 2D array by slicing the original array into appropriate chunks.
Step 1: Validation Check
First, we verify if the transformation is possible by checking if m * n != len(original)
. If the product of dimensions doesn't equal the array length, we immediately return an empty list []
since it's impossible to completely fill an m × n
matrix with the given elements.
if m * n != len(original):
return []
Step 2: Array Construction Using List Comprehension
Once validation passes, we construct the 2D array using Python's list comprehension with slicing:
return [original[i : i + n] for i in range(0, m * n, n)]
Let's break down this comprehension:
range(0, m * n, n)
generates starting indices:0, n, 2n, 3n, ...
up to(m-1) * n
- For each starting index
i
, we extract a sliceoriginal[i : i + n]
which gives us exactlyn
consecutive elements - Each slice becomes one row in our result
Why This Works:
The algorithm leverages the fact that in row-major order (which is how we're filling the 2D array), the element at position (row, col)
in the 2D array corresponds to index row * n + col
in the 1D array. By taking slices of size n
starting at multiples of n
, we're essentially reversing this mapping.
Time and Space Complexity:
- Time Complexity:
O(m * n)
as we need to process each element once - Space Complexity:
O(1)
extra space (not counting the output array which is required by the problem)
The beauty of this solution lies in its simplicity - we're not manually tracking row and column indices or using nested loops. Instead, we let Python's slicing handle the chunking operation efficiently.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with original = [1,2,3,4,5,6]
, m = 2
, and n = 3
.
Step 1: Validation Check
- Calculate
m * n = 2 * 3 = 6
- Check if
6 == len([1,2,3,4,5,6])
→6 == 6
✓ - Since they're equal, we can proceed with the transformation
Step 2: Determine Row Starting Indices
- We need to create 2 rows (m = 2), each with 3 elements (n = 3)
- Using
range(0, m * n, n)
→range(0, 6, 3)
generates indices:[0, 3]
- These are the starting positions for each row in the original array
Step 3: Extract Rows Using Slicing
-
First iteration (i = 0):
- Extract
original[0:0+3]
→original[0:3]
→[1,2,3]
- This becomes our first row
- Extract
-
Second iteration (i = 3):
- Extract
original[3:3+3]
→original[3:6]
→[4,5,6]
- This becomes our second row
- Extract
Step 4: Combine Results
- The list comprehension collects these slices:
[[1,2,3], [4,5,6]]
Visual Representation:
Original: [1, 2, 3, 4, 5, 6] ↓ ↓ ↓ ↓ ↓ ↓ Row 0: [1, 2, 3] Row 1: [4, 5, 6] Result: [[1, 2, 3], [4, 5, 6]]
The algorithm efficiently transforms the 1D array into a 2×3 matrix by taking consecutive chunks of 3 elements, demonstrating how the slicing approach naturally handles the row-wise reshaping.
Solution Implementation
1class Solution:
2 def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
3 # Check if the total elements match the required matrix dimensions
4 if m * n != len(original):
5 return []
6
7 # Create 2D array by slicing the original array into rows of length n
8 # Each row starts at index i and ends at index i+n
9 result = []
10 for i in range(0, m * n, n):
11 row = original[i:i + n]
12 result.append(row)
13
14 return result
15```
16
17Alternative implementation using list comprehension (more concise):
18
19```python3
20class Solution:
21 def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
22 # Validate that the 1D array can form an m x n matrix
23 if m * n != len(original):
24 return []
25
26 # Construct the 2D array by slicing original into n-sized chunks
27 # i iterates from 0 to m*n with step size n (0, n, 2n, ...)
28 return [original[i:i + n] for i in range(0, m * n, n)]
29
1class Solution {
2 /**
3 * Converts a 1D array into a 2D array with specified dimensions.
4 *
5 * @param original The input 1D array to be converted
6 * @param m The number of rows in the resulting 2D array
7 * @param n The number of columns in the resulting 2D array
8 * @return A 2D array with dimensions m x n, or empty array if conversion is impossible
9 */
10 public int[][] construct2DArray(int[] original, int m, int n) {
11 // Check if the total elements match the required 2D array dimensions
12 if (m * n != original.length) {
13 // Return empty 2D array if dimensions don't match
14 return new int[0][0];
15 }
16
17 // Initialize the result 2D array with specified dimensions
18 int[][] resultArray = new int[m][n];
19
20 // Iterate through each row
21 for (int row = 0; row < m; row++) {
22 // Iterate through each column in the current row
23 for (int col = 0; col < n; col++) {
24 // Map 1D array index to 2D array position
25 // Formula: row * numberOfColumns + column
26 resultArray[row][col] = original[row * n + col];
27 }
28 }
29
30 // Return the constructed 2D array
31 return resultArray;
32 }
33}
34
1class Solution {
2public:
3 vector<vector<int>> construct2DArray(vector<int>& original, int m, int n) {
4 // Check if the total elements match the required 2D array dimensions
5 // If not, return an empty 2D array
6 if (m * n != original.size()) {
7 return {};
8 }
9
10 // Initialize the result 2D array with m rows and n columns
11 vector<vector<int>> result(m, vector<int>(n));
12
13 // Iterate through each row
14 for (int row = 0; row < m; ++row) {
15 // Iterate through each column in the current row
16 for (int col = 0; col < n; ++col) {
17 // Map the 1D array index to 2D array position
18 // Formula: 1D index = row * number_of_columns + column
19 result[row][col] = original[row * n + col];
20 }
21 }
22
23 // Return the constructed 2D array
24 return result;
25 }
26};
27
1/**
2 * Converts a 1D array into a 2D array with specified dimensions
3 * @param original - The input 1D array to be converted
4 * @param m - Number of rows in the resulting 2D array
5 * @param n - Number of columns in the resulting 2D array
6 * @returns A 2D array with m rows and n columns, or empty array if impossible
7 */
8function construct2DArray(original: number[], m: number, n: number): number[][] {
9 // Check if the total elements match the required dimensions
10 if (m * n !== original.length) {
11 return [];
12 }
13
14 // Initialize the result 2D array
15 const result: number[][] = [];
16
17 // Iterate through the original array in chunks of size n
18 for (let startIndex = 0; startIndex < m * n; startIndex += n) {
19 // Extract a row of n elements and add to result
20 result.push(original.slice(startIndex, startIndex + n));
21 }
22
23 return result;
24}
25
Time and Space Complexity
Time Complexity: O(m × n)
The time complexity is determined by the list comprehension that creates the 2D array. The comprehension iterates m
times (once for each row), and for each iteration, it performs a slice operation original[i : i + n]
which takes O(n)
time to copy n
elements. Therefore, the total time complexity is O(m × n)
, which equals O(len(original))
since m × n = len(original)
when a valid 2D array can be constructed.
Space Complexity: O(1)
(excluding the output array)
If we don't count the space required for the output array (which is necessary for the answer), the space complexity is O(1)
. The algorithm only uses a constant amount of extra space for the loop variable i
in the list comprehension. The slicing operation creates new lists, but these are part of the required output rather than auxiliary space used by the algorithm itself.
If we include the output array, the space complexity would be O(m × n)
to store the resulting 2D array.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Errors in Range Calculation
A common mistake is using range(0, m, n)
instead of range(0, m * n, n)
. This would only generate m/n
rows instead of m
rows.
Incorrect:
return [original[i:i + n] for i in range(0, m, n)] # Wrong!
Correct:
return [original[i:i + n] for i in range(0, m * n, n)]
2. Forgetting the Validation Check
Omitting the dimension validation can lead to incorrect results when the array cannot perfectly form the desired matrix. Without this check, you might get:
- Incomplete rows if
len(original) < m * n
- Missing elements if
len(original) > m * n
Solution: Always validate first:
if m * n != len(original):
return []
3. Using Nested Loops with Index Calculation Errors
When using nested loops, a frequent error is incorrectly calculating the 1D index from 2D coordinates:
Incorrect:
result = []
for row in range(m):
current_row = []
for col in range(n):
index = row + col * m # Wrong formula!
current_row.append(original[index])
result.append(current_row)
Correct:
result = []
for row in range(m):
current_row = []
for col in range(n):
index = row * n + col # Correct: row * columns + col
current_row.append(original[index])
result.append(current_row)
4. Modifying the Original Array
Some might try to use pop()
or similar destructive operations on the original array:
Problematic:
result = []
for _ in range(m):
row = []
for _ in range(n):
row.append(original.pop(0)) # Modifies original and O(n) per pop!
result.append(row)
This approach has two issues:
- It modifies the input array (usually undesirable)
- Using
pop(0)
is O(n) for each operation, making the overall complexity O(m * n²)
Better approach: Use slicing which doesn't modify the original and maintains O(m * n) complexity.
Which data structure is used in a depth first search?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!