Failed Interviews - 1
A record of my failed “leet code style” interview questions.
The Problem
Given a 2D grid where:
0
represents an open cell.1
represents a blocked cell.
Determine if there’s a path from the top-left corner ([0, 0]
) to the bottom-right corner ([n-1, m-1]
) moving only right or down.
For example, in these grids:
const map1 = [
[0, 1, 0],
[0, 0, 0],
[0, 1, 0]
]; // Passable
const map2 = [
[0, 1, 0],
[0, 1, 0],
[0, 1, 0]
]; // not passable
My Solution
The first step was to model the grid as a graph where each cell is a node, and edges exist between adjacent open cells. From there, I implemented Breadth-First Search (BFS) to traverse the graph and track parent nodes, which allowed me to backtrack and verify if the path was valid.
The implementation is in TS as requested for the interview, making the solution a bit verbose.
Here’s how I approached it:
Step 1: Build the Graph
I represented the graph as an adjacency list, where each cell is a key, and the value is an array of its accessible neighbors.
const graph: Record<string, string[]> = {};
const maxY = map1.length
const maxX = map1[0].length
for (let y = 0; y < maxY; y++) {
for (let x = 0; x < maxX; x++) {
// Initialize the graph node
if (!graph[`${y}${x}`]) {
graph[`${y}${x}`] = [];
}
// Add neighbors if they’re open
// right check
if (x + 1 < maxX && map1[y][x + 1] !== 1) {
graph[`${y}${x}`].push(`${y}${x + 1}`);
}
// down check
if (y + 1 < maxY && map1[y + 1][x] !== 1) {
graph[`${y}${x}`].push(`${y + 1}${x}`);
}
}
}
The adjacency list for map1
would look like this:
// Map 1
{
"00": ["01", "10"],
"01": [],
"02": [],
"10": ["11", "20"],
"11": ["12"],
"12": ["22"],
"20": [],
"21": ["22"],
"22": []
}
Step 2: Traverse with BFS
Using BFS, I explored the graph while keeping track of visited nodes and parent-child relationships.
const queue: string[] = [];
const visited: string[] = [];
const parents: Record<string, string> = {};
const start = '00';
queue.push(start);
visited.push(start);
while (queue.length > 0) {
const s = queue.pop() as string;
for (const child of graph[s]) {
if (!visited.includes(child)) {
queue.push(child);
visited.push(child);
parents[child] = s; // Record the parent
}
}
}
Step 3: Backtrack and Check Passability
By backtracking from the end node to the start node using the parents
map, I verified whether the path was navigable.
const end = `${maxY - 1}${maxX - 1}`; // Bottom-right corner
let current = end;
const path = [];
while (current !== start && parents[current]) {
const p = parents[current];
if (p) {
path.unshift(p); // Add to the path
current = p; // Move to the parent
}
}
const passable = current === start; // Is passable if we reached the start
console.log(`Passable: ${passable}`);
if (passable) {
console.log(`Path: ${[...path, end].join(" -> ")}`);
}
The Result
When I ran the solution for the given map1
, here’s what I got:
Passable: true
Path: 00 -> 10 -> 11 -> 12 -> 22
and map2
:
Passable: false