Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Build confidence with an intuition-first walkthrough focused on array fundamentals.
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 <= 100Problem summary: 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: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[[1,2,3],[4,5,6],[7,8,9]] 1
[[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]] 4
[[1,2,3],[4,5,6],[7,8,9]] 9
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1260: Shift 2D Grid
class Solution {
public List<List<Integer>> shiftGrid(int[][] grid, int k) {
int m = grid.length, n = grid[0].length;
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < m; ++i) {
List<Integer> row = new ArrayList<>();
for (int j = 0; j < n; ++j) {
row.add(0);
}
ans.add(row);
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int idx = (i * n + j + k) % (m * n);
int x = idx / n, y = idx % n;
ans.get(x).set(y, grid[i][j]);
}
}
return ans;
}
}
// Accepted solution for LeetCode #1260: Shift 2D Grid
func shiftGrid(grid [][]int, k int) [][]int {
m, n := len(grid), len(grid[0])
ans := make([][]int, m)
for i := range ans {
ans[i] = make([]int, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
idx := (i*n + j + k) % (m * n)
x, y := idx/n, idx%n
ans[x][y] = grid[i][j]
}
}
return ans
}
# Accepted solution for LeetCode #1260: Shift 2D Grid
class Solution:
def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
m, n = len(grid), len(grid[0])
ans = [[0] * n for _ in range(m)]
for i, row in enumerate(grid):
for j, v in enumerate(row):
x, y = divmod((i * n + j + k) % (m * n), n)
ans[x][y] = v
return ans
// Accepted solution for LeetCode #1260: Shift 2D Grid
struct Solution;
impl Solution {
fn shift_grid(mut grid: Vec<Vec<i32>>, k: i32) -> Vec<Vec<i32>> {
let n = grid.len();
let m = grid[0].len();
let mut a = vec![];
for i in 0..n {
for j in 0..m {
a.push(grid[i][j]);
}
}
let s = n * m;
let mut k = s - (k as usize) % s;
for i in 0..n {
for j in 0..m {
grid[i][j] = a[k % s];
k += 1;
}
}
grid
}
}
#[test]
fn test() {
let grid = vec_vec_i32![[1, 2, 3], [4, 5, 6], [7, 8, 9]];
let k = 1;
let res: Vec<Vec<i32>> = vec_vec_i32![[9, 1, 2], [3, 4, 5], [6, 7, 8]];
assert_eq!(Solution::shift_grid(grid, k), res);
let grid = vec_vec_i32![[3, 8, 1, 9], [19, 7, 2, 5], [4, 6, 11, 10], [12, 0, 21, 13]];
let k = 4;
let res: Vec<Vec<i32>> =
vec_vec_i32![[12, 0, 21, 13], [3, 8, 1, 9], [19, 7, 2, 5], [4, 6, 11, 10]];
assert_eq!(Solution::shift_grid(grid, k), res);
}
// Accepted solution for LeetCode #1260: Shift 2D Grid
function shiftGrid(grid: number[][], k: number): number[][] {
const [m, n] = [grid.length, grid[0].length];
const ans: number[][] = Array.from({ length: m }, () => Array.from({ length: n }, () => 0));
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
const idx = (i * n + j + k) % (m * n);
const [x, y] = [Math.floor(idx / n), idx % n];
ans[x][y] = grid[i][j];
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.