Medium草稿★★★★★O(n^2) 時間 · O(n^2) 空間
GraphBFSMatrixMulti-Source BFS
Patterns🌊 廣度優先 BFS🕸️ 圖遍歷・連通分量
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

1162As Far from Land as PossibleGraphsMediumGraphs

給定一個 n x n 的網格 grid1 代表陸地、0 代表水域。求水域格子到最近陸地的曼哈頓距離中,最大的那個值。若全是陸地或全是水域,回傳 -1

Example:

Input: grid = [[1,0,1],[0,0,0],[1,0,1]] Output: 2

Intuition

TIP

多源 BFS — 從所有陸地同時出發,最後被到達的水域格子就是答案。

Approaches

⭐ 1. Multi-Source BFS — O(n^2) / O(n^2)
  • Idea: 所有陸地同時入隊,BFS 層層擴展,最後一層的距離即為答案
  • Time: O(n^2)
  • Space: O(n^2)
class Solution {
    fun maxDistance(grid: Array<IntArray>): Int {
        val n = grid.size
        val queue = ArrayDeque<IntArray>()

        for (i in 0 until n) {
            for (j in 0 until n) {
                if (grid[i][j] == 1) queue.add(intArrayOf(i, j))
            }
        }

        if (queue.size == 0 || queue.size == n * n) return -1

        val dirs = arrayOf(intArrayOf(0, 1), intArrayOf(0, -1), intArrayOf(1, 0), intArrayOf(-1, 0))
        var dist = -1

        while (queue.isNotEmpty()) {
            dist++
            repeat(queue.size) {
                val (r, c) = queue.removeFirst()
                for ((dr, dc) in dirs) {
                    val nr = r + dr
                    val nc = c + dc
                    if (nr in 0 until n && nc in 0 until n && grid[nr][nc] == 0) {
                        grid[nr][nc] = 1
                        queue.add(intArrayOf(nr, nc))
                    }
                }
            }
        }
        return dist
    }
}
2. Dynamic Programming — O(n^2) / O(n^2)
  • Idea: 兩次掃描:左上到右下、右下到左上,計算每個格子到最近陸地的距離
  • Time: O(n^2)
  • Space: O(n^2)
class Solution {
    fun maxDistance(grid: Array<IntArray>): Int {
        val n = grid.size
        val dist = Array(n) { IntArray(n) { n * 2 } }

        for (i in 0 until n) {
            for (j in 0 until n) {
                if (grid[i][j] == 1) dist[i][j] = 0
            }
        }

        // 左上到右下
        for (i in 0 until n) {
            for (j in 0 until n) {
                if (i > 0) dist[i][j] = minOf(dist[i][j], dist[i - 1][j] + 1)
                if (j > 0) dist[i][j] = minOf(dist[i][j], dist[i][j - 1] + 1)
            }
        }

        // 右下到左上
        var result = -1
        for (i in n - 1 downTo 0) {
            for (j in n - 1 downTo 0) {
                if (i < n - 1) dist[i][j] = minOf(dist[i][j], dist[i + 1][j] + 1)
                if (j < n - 1) dist[i][j] = minOf(dist[i][j], dist[i][j + 1] + 1)
                if (grid[i][j] == 0) result = maxOf(result, dist[i][j])
            }
        }

        return if (result == n * 2 || result == 0) -1 else result
    }
}

🔑 Takeaways