Welcome to Subscribe On Youtube
1020. Number of Enclaves
Description
You are given an m x n binary matrix grid, where 0 represents a sea cell and 1 represents a land cell.
A move consists of walking from one land cell to another adjacent (4-directionally) land cell or walking off the boundary of the grid.
Return the number of land cells in grid for which we cannot walk off the boundary of the grid in any number of moves.
Example 1:

Input: grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] Output: 3 Explanation: There are three 1s that are enclosed by 0s, and one 1 that is not enclosed because its on the boundary.
Example 2:

Input: grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] Output: 0 Explanation: All 1s are either on the boundary or can reach the boundary.
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 500grid[i][j]is either0or1.
Solutions
Solution 1: Depth-First Search
We can do a depth-first search starting with the land on the border, marking all land connected to the border as $0$. Finally, count the number of remaining $1$, which is the answer.
Time complexity $O(m \times n)$, space complexity $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the matrix respectively.
Solution 2
We can also use the breadth-first search method to queue up the land on the border, and then perform a breadth-first search to mark all land connected to the border as $0$. Finally, count the number of remaining $1$, which is the answer.
Time complexity $O(m \times n)$, space complexity $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the matrix respectively.
Solution 3
Thinking
Search still uses a stack or queue proportional to the component size. The same connectivity can be recorded with union-find: adjacent land is united, and every border land is united with a dummy exterior node.
Cells that stay land and are not in the exterior component are enclaves, so we count those sizes.
-
class Solution { private int m; private int n; private int[][] grid; public int numEnclaves(int[][] grid) { this.grid = grid; m = grid.length; n = grid[0].length; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] == 1 && (i == 0 || i == m - 1 || j == 0 || j == n - 1)) { dfs(i, j); } } } int ans = 0; for (var row : grid) { for (var v : row) { ans += v; } } return ans; } private void dfs(int i, int j) { grid[i][j] = 0; int[] dirs = {-1, 0, 1, 0, -1}; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) { dfs(x, y); } } } } // Solution 2 class Solution { public int numEnclaves(int[][] grid) { int m = grid.length; int n = grid[0].length; Deque<int[]> q = new ArrayDeque<>(); for (int j = 0; j < n; ++j) { for (int i : List.of(0, m - 1)) { if (grid[i][j] == 1) { q.offer(new int[] {i, j}); grid[i][j] = 0; } } } for (int i = 0; i < m; ++i) { for (int j : List.of(0, n - 1)) { if (grid[i][j] == 1) { q.offer(new int[] {i, j}); grid[i][j] = 0; } } } final int[] dirs = {-1, 0, 1, 0, -1}; while (!q.isEmpty()) { int[] p = q.poll(); int i = p[0], j = p[1]; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) { q.offer(new int[] {x, y}); grid[x][y] = 0; } } } int ans = 0; for (var row : grid) { for (int x : row) { ans += x; } } return ans; } } // Solution 3 class Solution { public int numEnclaves(int[][] grid) { int m = grid.length, n = grid[0].length; int[] dirs = {-1, 0, 1, 0, -1}; Deque<int[]> stk = new ArrayDeque<>(); for (int j = 0; j < n; j++) { for (int i : List.of(0, m - 1)) { if (grid[i][j] == 1) { flood(grid, stk, dirs, i, j); } } } for (int i = 0; i < m; i++) { for (int j : List.of(0, n - 1)) { if (grid[i][j] == 1) { flood(grid, stk, dirs, i, j); } } } int ans = 0; for (var row : grid) { for (int x : row) { ans += x; } } return ans; } private void flood(int[][] grid, Deque<int[]> stk, int[] dirs, int i, int j) { int m = grid.length, n = grid[0].length; grid[i][j] = 0; stk.push(new int[] {i, j}); while (!stk.isEmpty()) { int[] cur = stk.pop(); i = cur[0]; j = cur[1]; for (int k = 0; k < 4; k++) { int x = i + dirs[k], y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) { grid[x][y] = 0; stk.push(new int[] {x, y}); } } } } } -
class Solution { public: int numEnclaves(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); int dirs[5] = {-1, 0, 1, 0, -1}; function<void(int, int)> dfs = [&](int i, int j) { grid[i][j] = 0; for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y]) { dfs(x, y); } } }; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] && (i == 0 || i == m - 1 || j == 0 || j == n - 1)) { dfs(i, j); } } } int ans = 0; for (auto& row : grid) { for (auto& v : row) { ans += v; } } return ans; } }; // Solution 2 class Solution { public: int numEnclaves(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); int dirs[5] = {-1, 0, 1, 0, -1}; queue<pair<int, int>> q; for (int j = 0; j < n; ++j) { for (int i : {0, m - 1}) { if (grid[i][j] == 1) { q.emplace(i, j); grid[i][j] = 0; } } } for (int i = 0; i < m; ++i) { for (int j : {0, n - 1}) { if (grid[i][j] == 1) { q.emplace(i, j); grid[i][j] = 0; } } } while (!q.empty()) { auto [i, j] = q.front(); q.pop(); for (int k = 0; k < 4; ++k) { int x = i + dirs[k], y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) { q.emplace(x, y); grid[x][y] = 0; } } } int ans = 0; for (const auto& row : grid) { ans += accumulate(row.begin(), row.end(), 0); } return ans; } }; // Solution 3 class Solution { public: int numEnclaves(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); const int dirs[5] = {-1, 0, 1, 0, -1}; auto flood = [&](int i, int j) { vector<pair<int, int>> stk{{i, j}}; grid[i][j] = 0; while (!stk.empty()) { auto [a, b] = stk.back(); stk.pop_back(); for (int k = 0; k < 4; ++k) { int x = a + dirs[k], y = b + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) { grid[x][y] = 0; stk.emplace_back(x, y); } } } }; for (int j = 0; j < n; ++j) { for (int i : {0, m - 1}) { if (grid[i][j] == 1) { flood(i, j); } } } for (int i = 0; i < m; ++i) { for (int j : {0, n - 1}) { if (grid[i][j] == 1) { flood(i, j); } } } int ans = 0; for (const auto& row : grid) { ans += accumulate(row.begin(), row.end(), 0); } return ans; } }; -
class Solution: def numEnclaves(self, grid: List[List[int]]) -> int: def dfs(i, j): grid[i][j] = 0 for a, b in pairwise(dirs): x, y = i + a, j + b if 0 <= x < m and 0 <= y < n and grid[x][y]: dfs(x, y) m, n = len(grid), len(grid[0]) dirs = (-1, 0, 1, 0, -1) for i in range(m): for j in range(n): if grid[i][j] and (i == 0 or i == m - 1 or j == 0 or j == n - 1): dfs(i, j) return sum(v for row in grid for v in row) # Solution 2 class Solution: def numEnclaves(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) q = deque() for j in range(n): for i in (0, m - 1): if grid[i][j]: q.append((i, j)) grid[i][j] = 0 for i in range(m): for j in (0, n - 1): if grid[i][j]: q.append((i, j)) grid[i][j] = 0 dirs = (-1, 0, 1, 0, -1) while q: i, j = q.popleft() for a, b in pairwise(dirs): x, y = i + a, j + b if 0 <= x < m and 0 <= y < n and grid[x][y]: q.append((x, y)) grid[x][y] = 0 return sum(sum(row) for row in grid) # Solution 3 class Solution: def numEnclaves(self, grid: List[List[int]]) -> int: def flood(i: int, j: int): stk = [(i, j)] grid[i][j] = 0 while stk: i, j = stk.pop() for a, b in pairwise(dirs): x, y = i + a, j + b if 0 <= x < m and 0 <= y < n and grid[x][y]: grid[x][y] = 0 stk.append((x, y)) m, n = len(grid), len(grid[0]) dirs = (-1, 0, 1, 0, -1) for j in range(n): for i in (0, m - 1): if grid[i][j]: flood(i, j) for i in range(m): for j in (0, n - 1): if grid[i][j]: flood(i, j) return sum(sum(row) for row in grid) -
func numEnclaves(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) dirs := [5]int{-1, 0, 1, 0, -1} var dfs func(i, j int) dfs = func(i, j int) { grid[i][j] = 0 for k := 0; k < 4; k++ { x, y := i+dirs[k], j+dirs[k+1] if x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 { dfs(x, y) } } } for i, row := range grid { for j, v := range row { if v == 1 && (i == 0 || i == m-1 || j == 0 || j == n-1) { dfs(i, j) } } } for _, row := range grid { for _, v := range row { ans += v } } return } // Solution 2 func numEnclaves(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) dirs := [5]int{-1, 0, 1, 0, -1} q := [][2]int{} for j := 0; j < n; j++ { for _, i := range []int{0, m - 1} { if grid[i][j] == 1 { q = append(q, [2]int{i, j}) grid[i][j] = 0 } } } for i := 0; i < m; i++ { for _, j := range []int{0, n - 1} { if grid[i][j] == 1 { q = append(q, [2]int{i, j}) grid[i][j] = 0 } } } for len(q) > 0 { i, j := q[0][0], q[0][1] q = q[1:] for k := 0; k < 4; k++ { x, y := i+dirs[k], j+dirs[k+1] if x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 { q = append(q, [2]int{x, y}) grid[x][y] = 0 } } } for _, row := range grid { for _, x := range row { ans += x } } return } // Solution 3 func numEnclaves(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) dirs := [5]int{-1, 0, 1, 0, -1} flood := func(i, j int) { grid[i][j] = 0 stk := [][2]int{{i, j}} for len(stk) > 0 { cur := stk[len(stk)-1] stk = stk[:len(stk)-1] for k := 0; k < 4; k++ { x, y := cur[0]+dirs[k], cur[1]+dirs[k+1] if x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 { grid[x][y] = 0 stk = append(stk, [2]int{x, y}) } } } } for j := 0; j < n; j++ { for _, i := range [2]int{0, m - 1} { if grid[i][j] == 1 { flood(i, j) } } } for i := 0; i < m; i++ { for _, j := range [2]int{0, n - 1} { if grid[i][j] == 1 { flood(i, j) } } } for _, row := range grid { for _, x := range row { ans += x } } return } -
function numEnclaves(grid: number[][]): number { const m = grid.length; const n = grid[0].length; const dirs = [-1, 0, 1, 0, -1]; const dfs = (i: number, j: number) => { grid[i][j] = 0; for (let k = 0; k < 4; ++k) { const x = i + dirs[k]; const y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y <= n && grid[x][y] === 1) { dfs(x, y); } } }; for (let i = 0; i < m; ++i) { for (let j = 0; j < n; ++j) { if (grid[i][j] === 1 && (i === 0 || i === m - 1 || j === 0 || j === n - 1)) { dfs(i, j); } } } let ans = 0; for (const row of grid) { for (const v of row) { ans += v; } } return ans; } // Solution 2 function numEnclaves(grid: number[][]): number { const [m, n] = [grid.length, grid[0].length]; const dirs = [-1, 0, 1, 0, -1]; const q: number[][] = []; for (let j = 0; j < n; ++j) { for (let i of [0, m - 1]) { if (grid[i][j] === 1) { q.push([i, j]); grid[i][j] = 0; } } } for (let i = 0; i < m; ++i) { for (let j of [0, n - 1]) { if (grid[i][j] === 1) { q.push([i, j]); grid[i][j] = 0; } } } while (q.length) { const [i, j] = q.pop()!; for (let k = 0; k < 4; ++k) { const x = i + dirs[k]; const y = j + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] === 1) { q.push([x, y]); grid[x][y] = 0; } } } return grid.flat().reduce((acc, cur) => acc + cur, 0); } // Solution 3 function numEnclaves(grid: number[][]): number { const [m, n] = [grid.length, grid[0].length]; const dirs = [-1, 0, 1, 0, -1]; const flood = (i: number, j: number) => { grid[i][j] = 0; const stk: number[][] = [[i, j]]; while (stk.length) { const [a, b] = stk.pop()!; for (let k = 0; k < 4; ++k) { const x = a + dirs[k]; const y = b + dirs[k + 1]; if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] === 1) { grid[x][y] = 0; stk.push([x, y]); } } } }; for (let j = 0; j < n; ++j) { for (const i of [0, m - 1]) { if (grid[i][j] === 1) { flood(i, j); } } } for (let i = 0; i < m; ++i) { for (const j of [0, n - 1]) { if (grid[i][j] === 1) { flood(i, j); } } } return grid.flat().reduce((acc, cur) => acc + cur, 0); } -
impl Solution { fn dfs(grid: &mut Vec<Vec<i32>>, y: usize, x: usize) { if y >= grid.len() || x >= grid[0].len() || grid[y][x] == 0 { return; } grid[y][x] = 0; Solution::dfs(grid, y + 1, x); Solution::dfs(grid, y, x + 1); if y != 0 { Solution::dfs(grid, y - 1, x); } if x != 0 { Solution::dfs(grid, y, x - 1); } } pub fn num_enclaves(mut grid: Vec<Vec<i32>>) -> i32 { let mut res = 0; let m = grid.len(); let n = grid[0].len(); for i in 0..m { Solution::dfs(&mut grid, i, 0); Solution::dfs(&mut grid, i, n - 1); } for i in 0..n { Solution::dfs(&mut grid, 0, i); Solution::dfs(&mut grid, m - 1, i); } for i in 1..m - 1 { for j in 1..n - 1 { if grid[i][j] == 1 { res += 1; } } } res } } // Solution 2 use std::collections::VecDeque; impl Solution { pub fn num_enclaves(mut grid: Vec<Vec<i32>>) -> i32 { let m = grid.len(); let n = grid[0].len(); let mut q = VecDeque::new(); let dirs = [-1, 0, 1, 0, -1]; for j in 0..n { for &i in &[0, m - 1] { if grid[i][j] == 1 { q.push_back((i, j)); grid[i][j] = 0; } } } for i in 0..m { for &j in &[0, n - 1] { if grid[i][j] == 1 { q.push_back((i, j)); grid[i][j] = 0; } } } while let Some((i, j)) = q.pop_front() { for k in 0..4 { let x = i as isize + dirs[k]; let y = j as isize + dirs[k + 1]; if x >= 0 && x < m as isize && y >= 0 && y < n as isize { let (x, y) = (x as usize, y as usize); if grid[x][y] == 1 { q.push_back((x, y)); grid[x][y] = 0; } } } } grid.into_iter().flatten().sum() } } // Solution 3 impl Solution { pub fn num_enclaves(mut grid: Vec<Vec<i32>>) -> i32 { let m = grid.len(); let n = grid[0].len(); let dirs = [-1, 0, 1, 0, -1]; let flood = |grid: &mut Vec<Vec<i32>>, i: usize, j: usize| { grid[i][j] = 0; let mut stk = vec![(i, j)]; while let Some((a, b)) = stk.pop() { for k in 0..4 { let x = a as i32 + dirs[k]; let y = b as i32 + dirs[k + 1]; if x >= 0 && y >= 0 { let (x, y) = (x as usize, y as usize); if x < m && y < n && grid[x][y] == 1 { grid[x][y] = 0; stk.push((x, y)); } } } } }; for j in 0..n { if grid[0][j] == 1 { flood(&mut grid, 0, j); } if grid[m - 1][j] == 1 { flood(&mut grid, m - 1, j); } } for i in 0..m { if grid[i][0] == 1 { flood(&mut grid, i, 0); } if grid[i][n - 1] == 1 { flood(&mut grid, i, n - 1); } } grid.into_iter().flatten().filter(|&x| x == 1).count() as i32 } }