Given a 2D grid of size m x n and an integer k. You need to shift the grid k times.
In one shift operation:
grid[i][j] moves to grid[i][j + 1].grid[i][n - 1] moves to grid[i + 1][0].grid[m - 1][n - 1] moves to grid[0][0].Return the 2D grid after applying shift operation k times.
Example 1:
Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
Output: [[9,1,2],[3,4,5],[6,7,8]]
Example 2:
Input: grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
Output: [[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]
Example 3:
Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
Output: [[1,2,3],[4,5,6],[7,8,9]]
Constraints:
m == grid.lengthn == grid[i].length1 <= m <= 501 <= n <= 50-1000 <= grid[i][j] <= 10000 <= k <= 100When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine physically moving numbers in a grid to new spots like sliding tiles. The brute force way is to actually perform each movement one by one, step-by-step, until we've done all the shifts we need.
Here's how the algorithm would work step-by-step:
def shift_grid_brute_force(grid, shift_amount):
number_of_rows = len(grid)
number_of_columns = len(grid[0])
for _ in range(shift_amount):
# Store the last element of the grid
last_element = grid[number_of_rows - 1][number_of_columns - 1]
# Shift all elements one position to the right and down
previous_element = last_element
for row_index in range(number_of_rows):
for column_index in range(number_of_columns):
current_element = grid[row_index][column_index]
grid[row_index][column_index] = previous_element
previous_element = current_element
#The first element of grid is now the previous last element
return gridThe key to efficiently shifting the grid is to treat it as one long continuous sequence of numbers, reshape it, and then reshape it again. This avoids moving elements one by one, which would take much longer.
Here's how the algorithm would work step-by-step:
def shift_grid(grid, shift_amount):
number_of_rows = len(grid)
number_of_columns = len(grid[0])
# Flatten the 2D grid into a 1D list
flattened_grid = [element for row in grid for element in row]
total_elements = number_of_rows * number_of_columns
effective_shift = shift_amount % total_elements
# Shift the elements in the flattened grid
shifted_flattened_grid = flattened_grid[-effective_shift:] + flattened_grid[:-effective_shift]
# Reshape the shifted 1D list back into a 2D grid
shifted_grid = []
for row_index in range(number_of_rows):
# Reconstruct each row by taking slices of the flattened array.
shifted_grid.append(shifted_flattened_grid[row_index * number_of_columns:(row_index + 1) * number_of_columns])
return shifted_grid| Case | How to Handle |
|---|---|
| Null or empty grid | Return the original grid if it's null or empty to avoid NullPointerException or index out of bounds. |
| Zero shifts (k = 0) | If k is 0, return the original grid without performing any shifts. |
| Large shift value (k larger than grid size) | Use the modulo operator (k % (m * n)) to reduce k to an effective shift within the grid size. |
| 1x1 grid (single element) | A 1x1 grid shifting will always return the same grid, handle it correctly. |
| Rectangular grid (m != n) | Ensure the shifting logic correctly handles rectangular grids where the number of rows and columns are different. |
| Grid with very large dimensions (memory considerations) | Consider in-place shifting if memory constraints are a concern, trading space for time complexity. |
| Negative shift value (k < 0) | Handle negative shift values by converting them to positive equivalent (k = k % (m * n) + (m*n) if k < 0) to shift correctly. |
| Integer overflow in k calculation | Use long data type for k when calculating the effective shift to prevent integer overflow if grid dimensions are large. |