Back to Graphs
Number of Enclaves
Number of Enclaves
🧩 Problem Statement
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.
- The 1 at (1,0) is on the boundary, so we can walk off.
🔹 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 connected to the boundary.
🔍 Approaches
1. Flood Fill from Boundary
This is very similar to "Number of Closed Islands" and "Surrounded Regions".
- Identify "Safe" Lands:
- Iterate through the boundary cells of the grid.
- If a boundary cell is
1(land), start a DFS/BFS to mark all connected land cells as "unsafe" (can walk off). Mark them as visited (e.g., change1to0or2).
- Count Enclaves:
- Iterate through the entire grid.
- Any remaining
1s are enclaves (cannot walk off). - Count them (no need to run DFS again, just sum them up).
Algorithm Steps:
- Loop over boundary rows/cols.
- If
grid[i][j] == 1, callDFS(i, j).
DFSchanges1to0(sinking the island).
- Loop over all cells.
- If
grid[i][j] == 1, incrementcount.
⏳ Time & Space Complexity
- Time Complexity: $O(M \cdot N)$. We visit each cell constant times.
- Space Complexity: $O(M \cdot N)$ for recursion/queue.
🚀 Code Implementations
C++
#include <vector>
using namespace std;
class Solution {
public:
int numEnclaves(vector<vector<int>>& grid) {
int m = grid.size();
int n = grid[0].size();
// 1. Sink all land connected to the boundary
for(int i = 0; i < m; ++i) {
for(int j = 0; j < n; ++j) {
if((i == 0 || j == 0 || i == m - 1 || j == n - 1) && grid[i][j] == 1) {
dfs(grid, i, j, m, n);
}
}
}
// 2. Count remaining land
int count = 0;
for(int i = 0; i < m; ++i) {
for(int j = 0; j < n; ++j) {
if(grid[i][j] == 1) {
count++;
}
}
}
return count;
}
private:
void dfs(vector<vector<int>>& grid, int r, int c, int m, int n) {
if(r < 0 || r >= m || c < 0 || c >= n || grid[r][c] == 0) return;
grid[r][c] = 0; // Sink the land
dfs(grid, r + 1, c, m, n);
dfs(grid, r - 1, c, m, n);
dfs(grid, r, c + 1, m, n);
dfs(grid, r, c - 1, m, n);
}
};
Python
from typing import List
class Solution:
def numEnclaves(self, grid: List[List[int]]) -> int:
rows, cols = len(grid), len(grid[0])
def dfs(r, c):
if r < 0 or c < 0 or r >= rows or c >= cols or grid[r][c] == 0:
return
grid[r][c] = 0 # Sink
dfs(r + 1, c)
dfs(r - 1, c)
dfs(r, c + 1)
dfs(r, c - 1)
# 1. Sink boundary-connected land
for r in range(rows):
for c in range(cols):
if (r == 0 or c == 0 or r == rows - 1 or c == cols - 1) and grid[r][c] == 1:
dfs(r, c)
# 2. Count remaining
count = 0
for r in range(rows):
for c in range(cols):
if grid[r][c] == 1:
count += 1
return count
Java
class Solution {
public int numEnclaves(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
// 1. Sink boundary land
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if((i == 0 || j == 0 || i == m - 1 || j == n - 1) && grid[i][j] == 1) {
dfs(grid, i, j, m, n);
}
}
}
// 2. Count remaining
int count = 0;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(grid[i][j] == 1) {
count++;
}
}
}
return count;
}
private void dfs(int[][] grid, int r, int c, int m, int n) {
if(r < 0 || c < 0 || r >= m || c >= n || grid[r][c] == 0) return;
grid[r][c] = 0; // Sink
dfs(grid, r + 1, c, m, n);
dfs(grid, r - 1, c, m, n);
dfs(grid, r, c + 1, m, n);
dfs(grid, r, c - 1, m, n);
}
}
🌍 Real-World Analogy
Castles and Moats:
- The grid boundary is the "edge of the world" (freedom).
- Land connected to the edge allows escape.
- Enclaves are castles completely surrounded by the "sea" (0s) with no path to the edge.
🎯 Summary
✅ Preprocessing (Boundary Sinking): Eliminates all invalid paths first.
✅ Counting: After preprocessing, any remaining 1 is guaranteed to be an enclave.
Solution Code
O(n) TimeO(1) Space
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int numEnclaves(vector<vector<int>> &grid) {
int m = grid.size();
int n = grid[0].size();
// 1. Sink all land connected to the boundary
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if ((i == 0 || j == 0 || i == m - 1 || j == n - 1) && grid[i][j] == 1) {
dfs(grid, i, j, m, n);
}
}
}
// 2. Count remaining land
int count = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
count++;
}
}
}
return count;
}
private:
void dfs(vector<vector<int>> &grid, int r, int c, int m, int n) {
if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] == 0)
return;
grid[r][c] = 0; // Sink the land
dfs(grid, r + 1, c, m, n);
dfs(grid, r - 1, c, m, n);
dfs(grid, r, c + 1, m, n);
dfs(grid, r, c - 1, m, n);
}
};
int main() {
Solution sol;
vector<vector<int>> grid1 = {
{0, 0, 0, 0}, {1, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}};
cout << "Enclaves 1: " << sol.numEnclaves(grid1) << endl; // Expect 3
vector<vector<int>> grid2 = {
{0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}};
cout << "Enclaves 2: " << sol.numEnclaves(grid2) << endl; // Expect 0
return 0;
}
SYSTEM STABLEUTF-8 • STATIC_RENDER