Skip to content
← All posts

Shift 2D Grid: Flatten, Rotate, Reshape

5 min read
leetcodeproblemeasyarraysmatrixsimulation

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.

Before shift (k=1)123456789k=1After shift912345678
Each element moves one position forward in row-major order. The last element (9) wraps to position (0,0).

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

row-major order123456789

grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1.

Step 2: Flatten to a 1D array

123456789012345678

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

912345678012345678

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

result grid912345678

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

ApproachTimeSpace
Flatten and rotateO(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 k returns 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

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.