1914. Cyclically Rotating a Grid

  • Array
  • Matrix
  • Simulation
TIME
O(m × n)
SPACE
O(m + n)
problem on leetcode ↗source on github ↗

Intuition

Each layer is an independent cycle. If we list a layer's cells around the border, one rotation moves each value into the adjacent cell in the counter-clockwise direction. With the coordinate order used below, the value written at position i should come from position (i - k) % length.

Because k can be large, reduce it by the layer length.

Approach

  1. Process each layer from outside to inside.
  2. Collect the layer coordinates in counter-clockwise order:
    • down the left column
    • right along the bottom row
    • up the right column
    • left along the top row
  3. Store the values at those coordinates.
  4. For each coordinate index i, write values[(i - k) % length] back to that coordinate.

Complexity

  • Time: O(m × n), every cell belongs to exactly one layer
  • Space: O(m + n), temporary storage for one layer at a time

Edge Cases

  • 2 x 2 grid -> one layer with four cells
  • Large k -> use modulo per layer
  • Rectangular grids -> layer boundaries handle unequal dimensions

Code

from typing import List


class Solution:
    def rotateGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
        """
        1914. Cyclically Rotating a Grid
        Time: O(m × n)
        Space: O(m + n)
        """
        m, n = len(grid), len(grid[0])
        layers = min(m, n) // 2

        for layer in range(layers):
            coords = self._layer_coordinates(m, n, layer)
            values = [grid[row][col] for row, col in coords]
            shift = k % len(values)

            for i, (row, col) in enumerate(coords):
                grid[row][col] = values[(i - shift) % len(values)]

        return grid

    def _layer_coordinates(self, m: int, n: int, layer: int) -> List[tuple[int, int]]:
        top = layer
        bottom = m - 1 - layer
        left = layer
        right = n - 1 - layer
        coords = []

        for row in range(top, bottom + 1):
            coords.append((row, left))

        for col in range(left + 1, right + 1):
            coords.append((bottom, col))

        for row in range(bottom - 1, top - 1, -1):
            coords.append((row, right))

        for col in range(right - 1, left, -1):
            coords.append((top, col))

        return coords