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

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

1020Number of EnclavesGraphsMediumGraphs

給定一個二維網格 grid1 代表陸地、0 代表水域。求無法通過任意步數走到邊界的陸地格子數量(即被完全包圍的陸地格子數)。

Example:

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

Intuition

TIP

先淹沒所有與邊界相連的陸地,再計算剩餘陸地格子數。

Approaches

⭐ 1. DFS Flood from Border — O(m * n) / O(m * n)
  • Idea: 從邊界所有 1 開始 DFS 標記,最後計算未被標記的 1 數量
  • Time: O(m * n)
  • Space: O(m * n)(遞迴堆疊)
class Solution {
    fun numEnclaves(grid: Array<IntArray>): Int {
        val m = grid.size
        val n = grid[0].size

        fun dfs(i: Int, j: Int) {
            if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] != 1) return
            grid[i][j] = 0
            dfs(i + 1, j); dfs(i - 1, j); dfs(i, j + 1); dfs(i, j - 1)
        }

        // 淹沒邊界相連的陸地
        for (i in 0 until m) { dfs(i, 0); dfs(i, n - 1) }
        for (j in 0 until n) { dfs(0, j); dfs(m - 1, j) }

        // 計算剩餘陸地
        var count = 0
        for (i in 0 until m) {
            for (j in 0 until n) {
                if (grid[i][j] == 1) count++
            }
        }
        return count
    }
}
2. BFS Flood from Border — O(m * n) / O(m * n)
  • Idea: 用 BFS 替代 DFS,避免遞迴堆疊溢出
  • Time: O(m * n)
  • Space: O(m * n)
class Solution {
    fun numEnclaves(grid: Array<IntArray>): Int {
        val m = grid.size
        val n = grid[0].size
        val queue = ArrayDeque<IntArray>()
        val dirs = arrayOf(intArrayOf(0, 1), intArrayOf(0, -1), intArrayOf(1, 0), intArrayOf(-1, 0))

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

        while (queue.isNotEmpty()) {
            val (r, c) = queue.removeFirst()
            for ((dr, dc) in dirs) {
                val nr = r + dr
                val nc = c + dc
                if (nr in 0 until m && nc in 0 until n && grid[nr][nc] == 1) {
                    grid[nr][nc] = 0
                    queue.add(intArrayOf(nr, nc))
                }
            }
        }

        var count = 0
        for (i in 0 until m) for (j in 0 until n) if (grid[i][j] == 1) count++
        return count
    }
}

🔑 Takeaways