Cyclically Rotating a Grid

Medium
Watch on YouTube ↗

Solution

class Solution {
    public int[][] rotateGrid(int[][] grid, int k) {
        int m = grid.length, n = grid[0].length;

        int r1 = 0, r2=m-1, c1=0, c2=n-1; // Outer layer or ring

        while(r1< r2 && c1<c2) {
            int total = (r2-r1)*2 + (c2-c1)*2;
            int shift = k%total;
            int ring[] = new int[total]; // O(m+n)
            // O(m*n)
            int idx = 0;
            // top
            for(int j=c1; j<c2; j++)
                ring[idx++] = grid[r1][j];
            // right
            for(int i=r1; i<r2; i++)
                ring[idx++] = grid[i][c2];
            // bottom
            for(int j=c2; j>c1; j--)
                ring[idx++] = grid[r2][j];
            // left
            for(int i=r2; i>r1; i--)
                ring[idx++] = grid[i][c1];
            
            // shifting ring array
            reverse(ring, 0, shift-1);
            reverse(ring, shift, total-1);
            reverse(ring, 0, total-1);
            idx = 0;
            for(int j=c1; j<c2; j++)
              grid[r1][j] = ring[idx++];
            // right
            for(int i=r1; i<r2; i++)
                grid[i][c2] = ring[idx++];
            // bottom
            for(int j=c2; j>c1; j--)
                grid[r2][j] = ring[idx++];
            // left
            for(int i=r2; i>r1; i--)
                grid[i][c1] = ring[idx++];
            r1++;
            r2--;
            c1++;
            c2--;
        }

        return grid;
    }

    void reverse(int arr[], int l, int r) {
        while(l < r) {
            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            l++;
            r--;
        }
    }
}