Taro Logo

Shift 2D Grid

Easy
Amazon logo
Amazon
1 view
Topics:
Arrays

You are given a 2D grid of size m x n and an integer k. Your task is to shift the grid k times. A single shift operation is defined as follows:

  1. The element at grid[i][j] moves to grid[i][j + 1]. That is, each element moves one position to the right within its row.
  2. The element at grid[i][n - 1] (the last element of the i-th row) moves to grid[i + 1][0] (the first element of the next row). That is, the last element of each row is moved to the beginning of the next row.
  3. The element at grid[m - 1][n - 1] (the last element of the last row) moves to grid[0][0] (the first element of the first row). That is, the last element of the entire grid wraps around to the beginning.

Your function should return the modified 2D grid after applying the shift operation k times.

Example:

Consider the following grid and k value:

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

After applying the shift operation once, the grid becomes:

[[9, 1, 2], [3, 4, 5], [6, 7, 8]]

If we perform 9 shifts:

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

After applying the shift operation nine times, the grid becomes: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Write a function to efficiently shift the elements of a 2D grid k times and return the resulting grid.

Solution


Shifting Elements in a 2D Grid

Problem Description

Given a 2D grid of size m x n and an integer k, shift the grid k times. In one shift operation:

  • Element at grid[i][j] moves to grid[i][j + 1].
  • Element at grid[i][n - 1] moves to grid[i + 1][0].
  • Element at grid[m - 1][n - 1] moves to grid[0][0].

Return the 2D grid after applying shift operation k times.

Brute Force Solution

The brute force solution involves performing the shift operation k times. In each shift, we iterate through the grid and move each element to its new position according to the rules. This method is straightforward but not the most efficient.

Algorithm

  1. Repeat the shift operation k times.
  2. In each shift operation:
    • Store the last element of the grid in a temporary variable.
    • Iterate through the grid from the last element to the first, shifting elements to the right.
    • Place the stored last element into the first position of the grid.

Complexity Analysis

  • Time Complexity: O(k * m * n), where k is the number of shifts, m is the number of rows, and n is the number of columns.
  • Space Complexity: O(1), as we only use a constant amount of extra space.

Optimal Solution

A more efficient approach avoids repeated iterations by calculating the final position of each element directly. This can be done using modular arithmetic. The idea is to flatten the 2D array into a 1D array conceptually, shift the elements in the 1D array, and then map the elements back to the 2D array.

Algorithm

  1. Calculate the effective number of shifts: k = k % (m * n). This handles cases where k is larger than the total number of elements.
  2. Create a new grid to store the shifted elements.
  3. Iterate through the original grid.
  4. For each element at grid[i][j], calculate its new position (new_i, new_j) after k shifts.
  5. Place the element at grid[i][j] into the new_grid[new_i][new_j].
  6. Return the new_grid.

Calculating New Position

The new position can be calculated as follows:

  1. Convert the 2D index (i, j) to a 1D index: index = i * n + j.
  2. Calculate the new 1D index after shifting: new_index = (index + k) % (m * n).
  3. Convert the new_index back to 2D indices: new_i = new_index / n and new_j = new_index % n.

Complexity Analysis

  • Time Complexity: O(m * n), where m is the number of rows and n is the number of columns. We iterate through each element in the grid once.
  • Space Complexity: O(m * n), as we create a new grid to store the shifted elements.

Code Example (Java)

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<List<Integer>> shiftGrid(int[][] grid, int k) {
        int m = grid.length;
        int n = grid[0].length;
        k = k % (m * n);

        List<List<Integer>> newGrid = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            newGrid.add(new ArrayList<>());
            for (int j = 0; j < n; j++) {
                newGrid.get(i).add(0);
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int index = i * n + j;
                int newIndex = (index + k) % (m * n);
                int newI = newIndex / n;
                int newJ = newIndex % n;
                newGrid.get(newI).set(newJ, grid[i][j]);
            }
        }

        return newGrid;
    }
}

Edge Cases

  • Empty Grid: If the input grid is empty (m = 0 or n = 0), return an empty grid.
  • Zero Shifts: If k = 0, return the original grid.
  • Large k: If k is larger than m * n, take k modulo (m * n) to optimize the number of actual shifts.

Summary

The optimal solution provides a significant improvement in time complexity compared to the brute force method. By directly calculating the new positions using modular arithmetic, the algorithm avoids unnecessary repeated shifts, resulting in a more efficient solution.