Given a 2D&nbsp;grid consists of 0s (land)&nbsp;and 1s (water).&nbsp; An island is a maximal 4-directionally connected group of 0s and a closed island&nbsp;is an island totally&nbsp;(all left, top, right, bottom) surrounded by 1s.

Return the number of closed islands.

&nbsp;
Example 1:



Input: grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
Output: 2
Explanation: 
Islands in gray are closed because they are completely surrounded by water (group of 1s).

Example 2:



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


Example 3:

Input: grid = [[1,1,1,1,1,1,1],
&nbsp;              [1,0,0,0,0,0,1],
&nbsp;              [1,0,1,1,1,0,1],
&nbsp;              [1,0,1,0,1,0,1],
&nbsp;              [1,0,1,1,1,0,1],
&nbsp;              [1,0,0,0,0,0,1],
               [1,1,1,1,1,1,1]]
Output: 2


&nbsp;
Constraints:


	1 &lt;= grid.length, grid[0].length &lt;= 100
	0 &lt;= grid[i][j] &lt;=1


class Solution:
    '''主函数：计算封闭岛屿的数量'''
    def closedIsland(self, grid: List[List[int]]) -> int:
        result = 0
        m, n = len(grid), len(grid[0])
        self.direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
        
        # 遍历 grid，处理边缘陆地
        for j in range(n):
            self.dfs(grid, 0, j)
            self.dfs(grid, m - 1, j)
        for i in range(m):
            self.dfs(grid, i, 0)
            self.dfs(grid, i, n - 1)
        
        # 剩下都是封闭岛屿，遍历找结果
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 0:
                    result += 1
                    self.dfs(grid, i, j)
        return result
    
    '''从 (i, j) 开始，将与之相邻的陆地都变成海水'''
    def dfs(self, grid, i, j):
        m, n = len(grid), len(grid[0])
        # 超出索引边界
        if i < 0 or j < 0 or i >= m or j >= n:
            return
        # 已经是海水了
        if grid[i][j] == 1:
            return
        # 变成海水
        grid[i][j] = 1
        for d in self.direction:
            x = i + d[0]
            y = j + d[1]
            self.dfs(grid, x, y)
class Solution {
    boolean isClosed = true;
    public int closedIsland(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int count = 0;

        for(int i=1; i<m-1; i++){
            for(int j=1; j<n-1; j++){
                isClosed = true;
                if(grid[i][j] == 0){
                    dfs(grid, i, j);

                    if(isClosed){
                        count++;
                    }
                }
            }
        }

        return count;
    }

    public void dfs(int[][] grid, int i, int j){
        if(i<0 || j<0 || i> grid.length-1 || j> grid[0].length-1 || grid[i][j] != 0) return;

         grid[i][j] = 1; // to mark as visited

        if(i == 0 || j == 0 || i == grid.length -1 || j == grid[0].length - 1) isClosed = false;

        dfs(grid, i, j+1);
        dfs(grid, i, j-1);
        dfs(grid, i+1, j);
        dfs(grid, i-1, j);
    }
}
class Solution {
public:
    bool isValid(int i,int j,vector<vector<int>>&grid) {
        if(i >= 0 && i < grid.size() && j >= 0 && j < grid[0].size() && grid[i][j] == 0) {
            return true;
        }
        return false;
    }
    void DFS(int i,int j,vector<vector<int>>&grid) {
        grid[i][j] = 1;
        if(isValid(i + 1,j,grid)) {
            DFS(i + 1,j,grid);
        }
        if(isValid(i - 1,j,grid)) {
            DFS(i - 1,j,grid);
        }
        if(isValid(i,j + 1,grid)) {
            DFS(i,j + 1,grid);
        }
        if(isValid(i,j - 1,grid)) {
            DFS(i,j - 1,grid);
        }
    }
    int closedIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        for(int i = 0; i < m; i++) {
            int j = 0;
            if(grid[i][j] == 0) {
                DFS(i,j,grid);
            }
            j = n - 1;
            if(grid[i][j] == 0) {
                DFS(i,j,grid);
            }
        }
        for(int j = 0; j < n; j++) {
            int i = 0;
            if(grid[i][j] == 0) {
                DFS(i,j,grid);
            }
            i = m - 1;
            if(grid[i][j] == 0) {
                DFS(i,j,grid);
            }
        }
        int cnt = 0;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == 0) {
                    cnt++;
                    DFS(i,j,grid);
                }
            }
        }
        return cnt;
    }
};
/**
 * @param {number[][]} grid
 * @return {number}
 */
var closedIsland = function(grid) {
    let rows = grid.length;
    let cols = grid[0].length;
    let islandCount = 0; // Initial island count

    // For Quick Response
    if (rows <= 2 || cols <= 2) return islandCount;

    for (let i = 0; i <= rows - 1; i++) {
        for (let j = 0; j <= cols - 1; j++) {
            /*
                If land was found on the border, it can never be enclosed by water.
                So, mark the all the adjacent land across grid as visited.
            */
            if (grid[i][j] === 0 && (i == 0 || j == 0 || i == rows - 1 || j == cols - 1)) {
                dfs(i, j);
            }
        }
    }

    // If land is found, increase the count and walk around land(adjacent indexes) to mark them as visited.
    for (let i = 1; i <= rows - 1; i++) {
        for (let j = 1; j <= cols - 1; j++) {
            if (grid[i][j] === 0) {
                islandCount++;
                dfs(i, j);
            }
        }
    }

    // To walk around land and mark it as visited
    function dfs(x, y) {
        if (x < 0 || y < 0 || x >= rows || y >= cols) return;
        if (grid[x][y] !== 0) return;

        grid[x][y] = 2;

        dfs(x + 1, y);
        dfs(x, y + 1);
        dfs(x - 1, y);
        dfs(x, y - 1);
    }

    return islandCount;
};
Number of Closed Islands