# 286. Walls and Gates ![maze](https://images.theconversation.com/files/153404/original/image-20170119-26567-1bsql2r.jpg?ixlib=rb-1.1.0&q=45&auto=format&w=1200&h=900.0&fit=crop =450x) ### Idea 題目定義數值如下:<br /> - 門 = 0 - 牆壁 = -1 - 空屋 = 2<sup>31</sup> 這題要我們把二維陣列的所有空屋到門的最短路徑算出並直接替換。<br /> 口頭解釋很麻煩,直接貼 jest 的範例測試如下:<br /> ```javascript describe('wallsAndGates', () => { test('it fills each empty room with the distance to its nearest gate', () => { const INF = 2 ** 31, rooms1 = [ [INF, -1, 0, INF], [INF, INF, INF, -1], [INF, -1, INF, -1], [0, -1, INF, INF], ] wallsAndGates(rooms1) expect(rooms1).toEqual([ [3, -1, 0, 1], [2, 2, 1, -1], [1, -1, 2, -1], [0, -1, 3, 4], ]) }) }) ``` 想法如下:<br /> 1. 先找到門,並開始遞迴 DFS ; DFS 的目的是**持續尋找空屋,刷新空屋相對門的最短距離,向下尋找新的有效空屋**。 2. 因為是從門開始,最短距離 distance 之初始值為 0。 3. 避免訪問到超出安全邊界的 rooms[ i ][ j ]、門、牆壁。 4. 從上下左右四個方向拓展 DFS ,並把最短距離加一。 5. **避免無窮迴圈**(ex: 往上 → 往下 → 往上...),比較 distance 和當前 rooms[ i ][ j ]的大小,若前者比後者小或是相同代表不再需要被更新。 以下是 DFS 的解答:<br /> ```javascript function wallsAndGates(rooms) { const m = rooms.length if (!m) return 0 const n = rooms[0].length for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { rooms[i][j] === 0 && dfs(i, j, 0) } } function dfs(i, j, distance) { if (i < 0 || i >= m || j < 0 || j >= n || rooms[i][j] < distance) return rooms[i][j] = distance distance += 1 dfs(i - 1, j, distance) dfs(i + 1, j, distance) dfs(i, j - 1, distance) dfs(i, j + 1, distance) } } ``` 也可以使用 BFS 的方式得出一樣的答案,只需要一個 queue 去不斷蒐集可被更新的空屋並執行更新,直到 queue 內沒有任何需被節點時結束計算。<br /> 以下是 BFS 的解答:<br /> ```javascript function wallsAndGates(rooms) { const m = rooms.length, queue = [] if (!m) return 0 const n = rooms[0].length, vectors = [ [-1, 0], [1, 0], [0, -1], [0, 1], ] for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { rooms[i][j] === 0 && queue.push([i, j]) } } while (queue.length) { const [i, j] = queue.shift() for (let [vi, vj] of vectors) { const nextI = i + vi, nextJ = j + vj if ( nextI < 0 || nextI >= m || nextJ < 0 || nextJ >= n || rooms[nextI][nextJ] <= rooms[i][j] ) continue rooms[nextI][nextJ] = rooms[i][j] + 1 queue.push([nextI, nextJ]) } } } ``` ###### tags: `Leetcode` `JavaScript`