← Daily Logs
NeetCode 150

Islands and Treasure (Walls and Gates)

MediumJul 6, 2026graphbfsmulti-sourceshortest-path

Multi-source BFS: seed the queue with every treasure cell at once instead of a single start node, and let a 'drain the current level, then bump distance' loop stand in for the `[node, distance]` tuples `shortestPath` used for the exact same job.

The problem

Implement `islandsAndTreasure(grid)`, mutating an `m x n` grid in place. Each cell is one of: `0` (a treasure chest), `-1` (a wall, impassable), or `2147483647` (empty land). Fill every empty cell with the distance to its nearest chest, leaving walls untouched.

'Nearest' is over every chest at once, not just one, so a single BFS from one starting cell isn't enough — the search has to start from all of them simultaneously, so whichever chest's search reaches a given empty cell first is guaranteed to be the nearest.

The approach

Multi-source BFS seeds the queue with the coordinates of *every* `0` cell in one pass over the grid, marking each visited immediately. That's the only structural change from a single-source search: instead of `q = [source]`, it's `q = [...every treasure]` — the traversal after that point doesn't know or care how many sources it started from.

Distance isn't carried per-entry the way `shortestPath` carried `[node, distanceFromSource]`. Instead the outer `while` loop processes one full BFS 'level' at a time: `size = q.length` snapshots how many cells belong to the current distance, an inner `while (size > 0)` drains exactly that many off the front, and `distance` increments once per level rather than once per node. Every cell popped inside that inner loop is exactly `distance` steps from its nearest chest, so `grid[cr][cc] = distance` writes the answer the instant a cell is dequeued.

The neighbour check only enqueues cells still holding the sentinel `2147483647` — a wall (`-1`) or an already-filled cell just fails that comparison and gets skipped, so walls stay untouched and nothing is visited twice.

The solution

js
class Solution {
    /**
     * @param {number[][]} grid
     */
    islandsAndTreasure(grid) {
        const visited = new Set()
        const q = []

        // Pushing all the treasure cells as BFS sources
        for (let r = 0; r < grid.length; r++) {
            for (let c = 0; c < grid[0].length; c++) {
                if (grid[r][c] === 0) {
                    q.push([r, c])
                    visited.add(`${r},${c}`)
                }
            }
        }

        const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
        let distance = 0

        while (q.length) {
            let size = q.length
            while (size > 0) {
                const [cr, cc] = q.shift()
                grid[cr][cc] = distance

                for (let [dr, dc] of directions) {
                    const [nr, nc] = [cr + dr, cc + dc]
                    const nColInbound = nc >= 0 && nc < grid[0].length
                    const nRowInbound = nr >= 0 && nr < grid.length
                    const inBound = nColInbound && nRowInbound
                    const neighborPos = `${nr},${nc}`

                    if (inBound && grid[nr][nc] === 2147483647 && !visited.has(neighborPos)) {
                        visited.add(neighborPos)
                        q.push([nr, nc])
                    }
                }
                size--
            }
            distance++
        }
    }
}

Time O(R * C)Space O(R * C)

All entries