Fundamentals/Patterns/Graph — Grid BFS (Shortest Path)10 problems· Graph

BFS on a 2D grid using a queue, tracking distance

When to useShortest path on grid, level-by-level grid expansion (rotting oranges, walls and gates)

iterative
Move The Obstacle | Demolition Robot | Robot Find Path
move_the_obstacle
Treasure Island I
treasure_island_i
Treasure Island II
treasure_island_ii
Walls and Gates / Zombie in Matrix
walls_and_gates
Zombie Matrix
zombie_matrix
Jump Game
jump_game
Knight Minimum Moves
knight_shortest_path
01 Matrixmedium
01_matrix · no slots
Minimum Knight Movesmedium
minimum_knight_moves · no slots
Rotting Orangesmedium
rotting_oranges
INITIALIZE
queue with start + distance; visited set/grid
const rows = grid.length;
const cols = grid[0].length;
const visited = Array.from({ length: rows }, () => new Array(cols).fill(false));
visited[0][0] = true;
const queue = [[0, 0, 0]];
let head = 0;
const dx = [1, -1, 0, 0];
const dy = [0, 0, 1, -1];
const rows = matrix.length;
const cols = matrix[0].length;
const visited = Array.from({ length: rows }, () => new Array(cols).fill(false));
visited[0][0] = true;
const queue = [[0, 0, 0]];
const dx = [1, -1, 0, 0];
const dy = [0, 0, 1, -1];
const rows = matrix.length;
const cols = matrix[0].length;
const visited = Array.from({ length: rows }, () => new Array(cols).fill(false));
const queue = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (matrix[r][c] === 'S') { queue.push([r, c, 0]); visited[r][c] = true; }
}
}
const dx = [1, -1, 0, 0];
const dy = [0, 0, 1, -1];
const m = dungeonMap.length;
const n = dungeonMap[0].length;
const queue = [];
for (let r = 0; r < m; r++) {
for (let c = 0; c < n; c++) {
if (dungeonMap[r][c] === 0) queue.push([r, c, 0]);
}
}
const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
const m = matrix.length;
const n = matrix[0].length;
const queue = [];
let humans = 0;
for (let r = 0; r < m; r++) {
for (let c = 0; c < n; c++) {
if (matrix[r][c] === 1) queue.push([r, c, 0]);
else humans += 1;
}
}
const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
let days = 0;
const queue = [start];
const visited = new Set([start]);
const targetX = Math.abs(x);
const targetY = Math.abs(y);
const visited = new Set(['0,0']);
const queue = [[0, 0, 0]];
const moves = [[1,2],[2,1],[2,-1],[1,-2],[-1,-2],[-2,-1],[-2,1],[-1,2]];
const rows = grid.length;
const cols = grid[0].length;
const queue = [];
let fresh = 0;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (grid[r][c] === 2) queue.push([r, c, 0]);
else if (grid[r][c] === 1) fresh += 1;
}
}
const directions = [[1,0],[-1,0],[0,1],[0,-1]];
let minutes = 0;
TRAVERSE
while (queue.length)
while (head < queue.length) {
while (queue.length > 0) {
while (queue.length > 0) {
while (queue.length > 0) {
while (queue.length > 0) {
while (queue.length > 0) {
while (queue.length > 0) {
while (queue.length > 0) {
dequeue
pop front; check goal
const [r, c, dist] = queue[head++];
if (grid[r][c] === 9) return dist;
const [r, c, dist] = queue.shift();
if (matrix[r][c] === 'X') return dist;
const [r, c, dist] = queue.shift();
if (matrix[r][c] === 'X') return dist;
const [r, c, d] = queue.shift();
const [r, c, d] = queue.shift();
days = d;
const curr = queue.shift();
if (arr[curr] === 0) return true;
const [cx, cy, dist] = queue.shift();
if (cx === targetX && cy === targetY) return dist;
const [r, c, d] = queue.shift();
minutes = d;
expand
for each of 4 neighbors
for (let i = 0; i < 4; i++) {
const nr = r + dx[i];
const nc = c + dy[i];
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
for (let i = 0; i < 4; i++) {
const nr = r + dx[i];
const nc = c + dy[i];
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
for (let i = 0; i < 4; i++) {
const nr = r + dx[i];
const nc = c + dy[i];
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;
if (nr < 0 || nr >= m || nc < 0 || nc >= n) continue;
for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;
if (nr < 0 || nr >= m || nc < 0 || nc >= n) continue;
for (const next of [curr - arr[curr], curr + arr[curr]]) {
for (const [dx, dy] of moves) {
const nx = cx + dx;
const ny = cy + dy;
if (nx < -2 || ny < -2 || nx > targetX + 2 || ny > targetY + 2) continue;
for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;
if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
[VISIT]
if passable and unvisited: mark and enqueue with dist+1
if (visited[nr][nc] || grid[nr][nc] === 1) continue;
visited[nr][nc] = true;
queue.push([nr, nc, dist + 1]);
if (visited[nr][nc] || matrix[nr][nc] === 'D') continue;
visited[nr][nc] = true;
queue.push([nr, nc, dist + 1]);
if (visited[nr][nc] || matrix[nr][nc] === 'D') continue;
visited[nr][nc] = true;
queue.push([nr, nc, dist + 1]);
if (dungeonMap[nr][nc] !== 2147483647) continue;
dungeonMap[nr][nc] = d + 1;
queue.push([nr, nc, d + 1]);
if (matrix[nr][nc] !== 0) continue;
matrix[nr][nc] = 1;
humans -= 1;
queue.push([nr, nc, d + 1]);
if (next >= 0 && next < arr.length && !visited.has(next)) {
visited.add(next);
queue.push(next);
}
const key = nx + ',' + ny;
if (!visited.has(key)) {
visited.add(key);
queue.push([nx, ny, dist + 1]);
}
if (grid[nr][nc] !== 1) continue;
grid[nr][nc] = 2;
fresh -= 1;
queue.push([nr, nc, d + 1]);
RETURN
distance or result
return -1;
return -1;
return -1;
return dungeonMap;
return humans === 0 ? days : -1;
return false;
return -1;
return fresh === 0 ? minutes : -1;