Shift 2D Grid: Flatten, Rotate, Reshape
You are given an m x n 2D grid and an integer k. In one shift operation, every element moves to the next position in row-major order: each element at grid[i][j] moves to grid[i][j+1], the last element in each row wraps to the first position of the next row, and the very last element in the grid wraps around to grid[0][0]. Return the grid after applying k shift operations.
This is LeetCode 1260: Shift 2D Grid, and it is a great introduction to the flatten-rotate-reshape pattern. The technique you learn here applies to any problem where you need to treat a 2D matrix as a 1D sequence, transform it, and convert back.
Why this problem matters
Simulating the shift one element at a time would work, but it is slow. Each shift touches every element in the grid, and doing that k times means O(k * m * n) work. When k is large, that adds up fast.
The insight is that k individual shifts are equivalent to one rotation of the flattened array by k positions. Instead of simulating, you flatten the 2D grid into a 1D array, rotate it, and reshape it back. This reduces the problem to a well-known array rotation, and the entire operation takes O(m * n) time regardless of how large k is.
This "flatten, transform, reshape" pattern shows up whenever a problem describes a 2D operation that maps cleanly to a 1D operation. Once you see it here, you will recognize it in problems like Reshape the Matrix (LeetCode 566) and Spiral Matrix (LeetCode 54).
The solution
def shift_grid(grid: list[list[int]], k: int) -> list[list[int]]:
m, n = len(grid), len(grid[0])
total = m * n
k %= total
flat = [grid[r][c] for r in range(m) for c in range(n)]
rotated = flat[-k:] + flat[:-k]
return [rotated[r * n:(r + 1) * n] for r in range(m)]
Let's walk through what each piece does.
First, we grab the dimensions m (rows) and n (columns). The total number of elements is m * n. We take k % total because shifting by the full length of the array brings you back to the start, so any extra full rotations are wasted work.
Next, we flatten the 2D grid into a 1D list by reading elements row by row. This is the row-major order that the problem describes.
The rotation itself is a single slice operation. flat[-k:] grabs the last k elements (these are the ones that wrap around to the front), and flat[:-k] grabs everything else. Concatenating them gives the rotated array.
Finally, we reshape the 1D array back into a 2D grid by slicing it into chunks of n elements, one chunk per row.
Always apply k %= total before rotating. Without it, slicing with a k larger than the array length produces wrong results. This modular arithmetic trick works because rotating an array by its own length is a no-op.
Visual walkthrough
Watch how the flatten-rotate-reshape approach transforms a 3x3 grid with k = 1. Each step card shows one phase of the algorithm.
Step 1: Original 3x3 grid
grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1.
Step 2: Flatten to a 1D array
Read the grid row by row: [1, 2, 3, 4, 5, 6, 7, 8, 9].
Step 3: Rotate the 1D array right by k=1
The last element (9) moves to the front: [9, 1, 2, 3, 4, 5, 6, 7, 8].
Step 4: Reshape back into a 3x3 grid
Take every 3 elements as a row: [[9,1,2],[3,4,5],[6,7,8]]. Done.
The key observation is that the 2D shift is just a 1D rotation in disguise. By flattening first, you reduce a tricky 2D simulation to a single array rotation that you can do in one pass.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Flatten and rotate | O(m * n) | O(m * n) |
Time is O(m * n) where m is the number of rows and n is the number of columns. Flattening visits every element once. Slicing and concatenating the rotated array is linear. Reshaping is another linear pass. The total work is proportional to the grid size, and it does not depend on k at all (thanks to the modulo).
Space is O(m * n) because we create a new flattened array and a new result grid. You could do the shift in-place using the three-reverse rotation trick, but the slice approach is cleaner and the space cost is the same order as the output.
The building blocks
1. 2D to 1D index mapping
Converting between 2D coordinates and a flat index is the foundation of this problem:
flat_index = row * num_cols + col
row = flat_index // num_cols
col = flat_index % num_cols
This mapping lets you treat any 2D grid as a 1D array and convert back. You will use it in Spiral Matrix, Reshape the Matrix, Search a 2D Matrix, and many other grid problems. The formula works for any rectangular grid, not just square ones.
2. Array rotation by k positions
Rotating an array right by k positions means moving the last k elements to the front:
k %= len(arr)
rotated = arr[-k:] + arr[:-k]
This is the same technique from Rotate Array (LeetCode 189). The modulo handles cases where k is larger than the array. The slice-and-concatenate approach is the most readable way to rotate in Python, although you can also do it in-place with three reversals if you need O(1) extra space.
Edge cases
Before submitting, think through these scenarios:
- k equals 0: no shift needed. Return the original grid.
- k equals m * n: a full rotation brings the grid back to its original state. The modulo handles this automatically.
- k larger than m * n: the modulo reduces it to an equivalent smaller rotation.
- Single row grid: the shift is just a 1D array rotation. The flatten-reshape approach handles this without special-casing.
- Single column grid: each element moves down by one position, and the bottom element wraps to the top. The flatten approach handles this correctly too.
- 1x1 grid: only one element. Any value of
kreturns the same grid.
From understanding to recall
You have seen how to flatten a 2D grid, rotate a 1D array, and reshape it back. The logic is simple and the code is short. But under interview pressure, the details matter. Do you remember to take k % total? Do you slice with flat[-k:] or flat[:k]? Do you reshape with r * n or r * m?
These are not conceptual gaps. They are recall gaps. Spaced repetition closes them. You practice writing the flatten step, the rotation, and the reshape from memory at increasing intervals. After a few rounds, the pattern is automatic. You see "shift elements in a grid" and the flatten-rotate-reshape template flows out without hesitation.
Related posts
- Rotate Array - The 1D array rotation pattern this problem builds on
- Spiral Matrix - Another matrix traversal pattern using index manipulation
- Reshape the Matrix - Flattening and reshaping between 2D dimensions
CodeBricks breaks Shift 2D Grid into its flatten, rotate, and reshape building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When an array manipulation problem shows up in your interview, you do not think about it. You just write it.