Given a binary matrix mat[][] where 1 represents land and 0 represents water, find the number of closed islands in the matrix.
An island is defined as a group of 1s connected horizontally or vertically (up, down, left, right). A closed island is an island that is completely surrounded by water (0) on all four sides and does not touch the boundary of the matrix.
Examples:
Input: mat[][] = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] Output: 1 Explanation: The land cell at (1,1) is surrounded on all four sides by 0s (water), so it forms a closed island. The land cells at (0,0) and (2,2) are not closed islands because they lie on the boundary of the matrix.
Input: mat[][] = [[0, 0, 0, 0, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 1]] Output: 1 Explanation: The closed island is the large block of land cells in the center. It is completely surrounded by water on all four sides. The land cell at (3,4) lies on the boundary of the matrix, so it cannot be considered a closed island.
[Approach - 1] Using DFS Traversal in Two Pass- O(N × M) and O(N × M) Space
The idea is to use Depth First Search (DFS). First, we traverse all the boundary cells of the matrix. If a boundary cell is land, we perform DFS from that cell to mark all connected land cells as visited — because any land connected to the boundary cannot form a closed island. After marking all boundary, we traverse the entire grid again. For every unvisited land cell, we perform DFS to explore all connected cells. Each such DFS call represents one closed island.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Ends// DFS to mark all connected land cells as visitedvoiddfs(vector<vector<int>>&matrix,vector<vector<bool>>&visited,intx,inty,intn,intm){if(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]==0)return;visited[x][y]=true;// Traverse to all adjacent elementsdfs(matrix,visited,x+1,y,n,m);dfs(matrix,visited,x-1,y,n,m);dfs(matrix,visited,x,y+1,n,m);dfs(matrix,visited,x,y-1,n,m);}// Count the closed islandintclosedIsland(vector<vector<int>>&matrix){intn=matrix.size(),m=matrix[0].size();vector<vector<bool>>visited(n,vector<bool>(m,false));// Mark islands connected to the boundary for(inti=0;i<n;++i){for(intj=0;j<m;++j){//check it is boundary and not visitedif((i*j==0||i==n-1||j==m-1)&&matrix[i][j]==1&&!visited[i][j]){dfs(matrix,visited,i,j,n,m);}}}intresult=0;// Count remaining unvisited islands (closed islands)for(inti=0;i<n;++i){for(intj=0;j<m;++j){if(matrix[i][j]==1&&!visited[i][j]){result++;dfs(matrix,visited,i,j,n,m);}}}returnresult;}//Driver Code Startsintmain(){vector<vector<int>>matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};cout<<closedIsland(matrix);return0;}//Driver Code Ends
Java
//Driver Code StartsclassGFG{//Driver Code Ends// DFS to mark all connected land cells as visitedstaticvoiddfs(int[][]matrix,boolean[][]visited,intx,inty,intn,intm){if(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]==0)return;visited[x][y]=true;// Traverse to all adjacent elementsdfs(matrix,visited,x+1,y,n,m);dfs(matrix,visited,x-1,y,n,m);dfs(matrix,visited,x,y+1,n,m);dfs(matrix,visited,x,y-1,n,m);}// Count the closed islandstaticintclosedIsland(int[][]matrix){intn=matrix.length,m=matrix[0].length;boolean[][]visited=newboolean[n][m];// Mark islands connected to the boundary for(inti=0;i<n;++i){for(intj=0;j<m;++j){//check it is boundary and not visitedif((i*j==0||i==n-1||j==m-1)&&matrix[i][j]==1&&!visited[i][j]){dfs(matrix,visited,i,j,n,m);}}}intresult=0;// Count remaining unvisited islands (closed islands)for(inti=0;i<n;++i){for(intj=0;j<m;++j){if(matrix[i][j]==1&&!visited[i][j]){result++;dfs(matrix,visited,i,j,n,m);}}}returnresult;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]mat={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};System.out.print(closedIsland(mat));}}//Driver Code Ends
Python
# DFS to mark all connected land cells as visiteddefdfs(matrix,visited,x,y,n,m):if(x<0ory<0orx>=nory>=morvisited[x][y]ormatrix[x][y]==0):returnvisited[x][y]=True# Traverse to all adjacent elementsdfs(matrix,visited,x+1,y,n,m)dfs(matrix,visited,x-1,y,n,m)dfs(matrix,visited,x,y+1,n,m)dfs(matrix,visited,x,y-1,n,m)# Count the closed islanddefclosedIsland(matrix):n=len(matrix)m=len(matrix[0])visited=[[Falsefor_inrange(m)]for_inrange(n)]# Mark islands connected to the boundary foriinrange(n):forjinrange(m):#check it is boundary and not visitedif((i*j==0ori==n-1orj==m-1)andmatrix[i][j]==1andnotvisited[i][j]):dfs(matrix,visited,i,j,n,m)result=0# Count remaining unvisited islands (closed islands)foriinrange(n):forjinrange(m):ifmatrix[i][j]==1andnotvisited[i][j]:result+=1dfs(matrix,visited,i,j,n,m)returnresult#Driver Code Startsif__name__=="__main__":matrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]]print(closedIsland(matrix))#Driver Code Ends
C#
//Driver Code StartsusingSystem;classGFG{//Driver Code Ends// DFS to mark all connected land cells as visitedvoiddfs(int[,]matrix,bool[,]visited,intx,inty,intn,intm){if(x<0||y<0||x>=n||y>=m||visited[x,y]||matrix[x,y]==0)return;visited[x,y]=true;// Traverse in 4 directionsdfs(matrix,visited,x+1,y,n,m);dfs(matrix,visited,x-1,y,n,m);dfs(matrix,visited,x,y+1,n,m);dfs(matrix,visited,x,y-1,n,m);}// Count the closed islandspublicintclosedIslands(int[,]matrix){intn=matrix.GetLength(0);intm=matrix.GetLength(1);bool[,]visited=newbool[n,m];// Mark islands connected to the boundary for(inti=0;i<n;++i){for(intj=0;j<m;++j){// check if boundary and not visitedif((i*j==0||i==n-1||j==m-1)&&matrix[i,j]==1&&!visited[i,j]){dfs(matrix,visited,i,j,n,m);}}}intresult=0;// Count remaining unvisited islands (closed islands)for(inti=0;i<n;++i){for(intj=0;j<m;++j){if(matrix[i,j]==1&&!visited[i,j]){result++;dfs(matrix,visited,i,j,n,m);}}}returnresult;}//Driver Code StartsstaticvoidMain(string[]args){int[,]matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};GFGsol=newGFG();intresult=sol.closedIslands(matrix);Console.WriteLine(result);}}//Driver Code Ends
JavaScript
//DFS to mark all connected land cells as visitedfunctiondfs(matrix,visited,x,y,n,m){if(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]===0){return;}visited[x][y]=true;// Traverse to all adjacent elementsdfs(matrix,visited,x+1,y,n,m);dfs(matrix,visited,x-1,y,n,m);dfs(matrix,visited,x,y+1,n,m);dfs(matrix,visited,x,y-1,n,m);}// Count the closed islandfunctionclosedIsland(matrix){letn=matrix.length;letm=matrix[0].length;letvisited=Array.from({length:n},()=>Array(m).fill(false));// Mark islands connected to the boundaryfor(leti=0;i<n;i++){for(letj=0;j<m;j++){//check it is boundary and not visitedif((i*j===0||i===n-1||j===m-1)&&matrix[i][j]===1&&!visited[i][j]){dfs(matrix,visited,i,j,n,m);}}}letresult=0;// Count remaining unvisited islands (closed islands)for(leti=0;i<n;i++){for(letj=0;j<m;j++){if(matrix[i][j]===1&&!visited[i][j]){result++;dfs(matrix,visited,i,j,n,m);}}}returnresult;}// Driver code //Driver Code Startsletmatrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]];console.log(closedIsland(matrix));//Driver Code Ends
Output
2
[Approach - 2] Using DFS Traversal in One Pass – O(N × M) Time and O(N × M) Space
Instead of performing two separate DFS traversals, we perform a single DFS directly from each unvisited land cell. We also maintain a boolean variable (hasBoundary) to track whether the current island touches the boundary. During DFS, if we encounter any land cell (1) that lies on the boundary, we set hasBoundary variable to true, indicating that this island is not closed. After the DFS traversal for that island completes, we check hasBoundary variable if it’s false, it means the island did not touch any boundary, so we count it as a closed island.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Ends// DFS to mark all connected land cells as visitedvoiddfs(vector<vector<int>>&matrix,vector<vector<bool>>&visited,intx,inty,intn,intm,bool&hasBoundary){// Base caseif(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]==0)return;// Mark if the current land cell lies on the boundaryif(x==0||y==0||x==n-1||y==m-1)hasBoundary=true;visited[x][y]=true;// Explore all 4 directionsdfs(matrix,visited,x+1,y,n,m,hasBoundary);dfs(matrix,visited,x-1,y,n,m,hasBoundary);dfs(matrix,visited,x,y+1,n,m,hasBoundary);dfs(matrix,visited,x,y-1,n,m,hasBoundary);}// Count the number of closed islandsintclosedIsland(vector<vector<int>>&matrix){intn=matrix.size(),m=matrix[0].size();vector<vector<bool>>visited(n,vector<bool>(m,false));intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]==1&&!visited[i][j]){boolhasBoundary=false;dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary)result++;}}}returnresult;}//Driver Code Startsintmain(){vector<vector<int>>matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};cout<<closedIsland(matrix);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;publicclassGFG{//Driver Code Ends// DFS to mark all connected land cells as visitedstaticvoiddfs(int[][]matrix,boolean[][]visited,intx,inty,intn,intm,boolean[]hasBoundary){// Base caseif(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]==0)return;// Mark if the current land cell lies on the boundaryif(x==0||y==0||x==n-1||y==m-1)hasBoundary[0]=true;visited[x][y]=true;// Explore all 4 directionsdfs(matrix,visited,x+1,y,n,m,hasBoundary);dfs(matrix,visited,x-1,y,n,m,hasBoundary);dfs(matrix,visited,x,y+1,n,m,hasBoundary);dfs(matrix,visited,x,y-1,n,m,hasBoundary);}// Count the number of closed islandsstaticintclosedIsland(int[][]matrix){intn=matrix.length,m=matrix[0].length;boolean[][]visited=newboolean[n][m];intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]==1&&!visited[i][j]){boolean[]hasBoundary={false};dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary[0])result++;}}}returnresult;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};System.out.println(closedIsland(matrix));}}//Driver Code Ends
Python
# DFS to mark all connected land cells as visiteddefdfs(matrix,visited,x,y,n,m,hasBoundary):# Base caseifx<0ory<0orx>=nory>=morvisited[x][y]ormatrix[x][y]==0:return# Mark if the current land cell lies on the boundaryifx==0ory==0orx==n-1ory==m-1:hasBoundary[0]=Truevisited[x][y]=True# Explore all 4 directionsdfs(matrix,visited,x+1,y,n,m,hasBoundary)dfs(matrix,visited,x-1,y,n,m,hasBoundary)dfs(matrix,visited,x,y+1,n,m,hasBoundary)dfs(matrix,visited,x,y-1,n,m,hasBoundary)# Count the number of closed islandsdefclosedIsland(matrix):n,m=len(matrix),len(matrix[0])visited=[[Falsefor_inrange(m)]for_inrange(n)]result=0# Start DFS for land cells foriinrange(n):forjinrange(m):#Check it is land cell and not visitedifmatrix[i][j]==1andnotvisited[i][j]:hasBoundary=[False]dfs(matrix,visited,i,j,n,m,hasBoundary)# Count only if not touching boundaryifnothasBoundary[0]:result+=1returnresult#Driver Code Startsif__name__=="__main__":matrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]]print(closedIsland(matrix))#Driver Code Ends
C#
//Driver Code StartsusingSystem;classGFG{//Driver Code Ends// DFS to mark all connected land cells as visitedstaticvoiddfs(int[,]matrix,bool[,]visited,intx,inty,intn,intm,refboolhasBoundary){// Base caseif(x<0||y<0||x>=n||y>=m||visited[x,y]||matrix[x,y]==0)return;// Mark if the current land cell lies on the boundaryif(x==0||y==0||x==n-1||y==m-1)hasBoundary=true;visited[x,y]=true;// Explore all 4 directionsdfs(matrix,visited,x+1,y,n,m,refhasBoundary);dfs(matrix,visited,x-1,y,n,m,refhasBoundary);dfs(matrix,visited,x,y+1,n,m,refhasBoundary);dfs(matrix,visited,x,y-1,n,m,refhasBoundary);}// Count the number of closed islandsstaticintclosedIsland(int[,]matrix){intn=matrix.GetLength(0),m=matrix.GetLength(1);bool[,]visited=newbool[n,m];intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i,j]==1&&!visited[i,j]){boolhasBoundary=false;dfs(matrix,visited,i,j,n,m,refhasBoundary);// Count only if not touching boundaryif(!hasBoundary)result++;}}}returnresult;}//Driver Code StartsstaticvoidMain(){int[,]matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};Console.WriteLine(closedIsland(matrix));}}//Driver Code Ends
JavaScript
// DFS to mark all connected land cells as visitedfunctiondfs(matrix,visited,x,y,n,m,hasBoundary){// Base caseif(x<0||y<0||x>=n||y>=m||visited[x][y]||matrix[x][y]===0)return;// Mark if the current land cell lies on the boundaryif(x===0||y===0||x===n-1||y===m-1)hasBoundary.value=true;visited[x][y]=true;// Explore all 4 directionsdfs(matrix,visited,x+1,y,n,m,hasBoundary);dfs(matrix,visited,x-1,y,n,m,hasBoundary);dfs(matrix,visited,x,y+1,n,m,hasBoundary);dfs(matrix,visited,x,y-1,n,m,hasBoundary);}// Count the number of closed islandsfunctionclosedIsland(matrix){constn=matrix.length,m=matrix[0].length;constvisited=Array.from({length:n},()=>Array(m).fill(false));letresult=0;// Start DFS for land cells for(leti=0;i<n;++i){for(letj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]===1&&!visited[i][j]){lethasBoundary={value:false};dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary.value)result++;}}}returnresult;}//Driver Code//Driver Code Startsconstmatrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]];console.log(closedIsland(matrix));//Driver Code Ends
Output
2
[Approach – 3] Using BFS Traversal – O(N × M) Time and O(N × M) Space
The idea is similar to the DFS-based approach, but here we use Breadth-First Search (BFS) instead of DFS to count the number of closed islands.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>usingnamespacestd;//Driver Code Ends// BFS to mark all connected land cells as visitedvoiddfs(vector<vector<int>>&matrix,vector<vector<bool>>&visited,intx,inty,intn,intm,bool&hasBoundary){queue<pair<int,int>>q;q.push({x,y});visited[x][y]=true;// Directions: up, down, left, rightintdx[]={1,-1,0,0};intdy[]={0,0,1,-1};while(!q.empty()){auto[cx,cy]=q.front();q.pop();// Mark if the current land cell lies on the boundaryif(cx==0||cy==0||cx==n-1||cy==m-1)hasBoundary=true;// Explore all 4 directionsfor(intdir=0;dir<4;++dir){intnx=cx+dx[dir];intny=cy+dy[dir];// Check boundaries and unvisited landif(nx>=0&&ny>=0&&nx<n&&ny<m&&!visited[nx][ny]&&matrix[nx][ny]==1){visited[nx][ny]=true;q.push({nx,ny});}}}}// Count the number of closed islandsintclosedIsland(vector<vector<int>>&matrix){intn=matrix.size(),m=matrix[0].size();vector<vector<bool>>visited(n,vector<bool>(m,false));intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]==1&&!visited[i][j]){boolhasBoundary=false;dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary)result++;}}}returnresult;}//Driver Code Startsintmain(){vector<vector<int>>matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};cout<<closedIsland(matrix);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Arrays;importjava.util.Queue;importjava.util.LinkedList;publicclassGFG{//Driver Code Ends// BFS to mark all connected land cells as visitedstaticvoiddfs(int[][]matrix,boolean[][]visited,intx,inty,intn,intm,boolean[]hasBoundary){Queue<int[]>q=newLinkedList<>();q.offer(newint[]{x,y});visited[x][y]=true;// Directions: up, down, left, rightint[]dx={1,-1,0,0};int[]dy={0,0,1,-1};while(!q.isEmpty()){int[]cell=q.poll();intcx=cell[0],cy=cell[1];// Mark if the current land cell lies on the boundaryif(cx==0||cy==0||cx==n-1||cy==m-1)hasBoundary[0]=true;// Explore all 4 directionsfor(intdir=0;dir<4;++dir){intnx=cx+dx[dir];intny=cy+dy[dir];// Check boundaries and unvisited landif(nx>=0&&ny>=0&&nx<n&&ny<m&&!visited[nx][ny]&&matrix[nx][ny]==1){visited[nx][ny]=true;q.offer(newint[]{nx,ny});}}}}// Count the number of closed islandsstaticintclosedIsland(int[][]matrix){intn=matrix.length,m=matrix[0].length;boolean[][]visited=newboolean[n][m];intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]==1&&!visited[i][j]){boolean[]hasBoundary={false};dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary[0])result++;}}}returnresult;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};System.out.println(closedIsland(matrix));}}//Driver Code Ends
Python
#Driver Code Startsfromcollectionsimportdeque#Driver Code Ends# BFS to mark all connected land cells as visiteddefdfs(matrix,visited,x,y,n,m,hasBoundary):q=deque()q.append((x,y))visited[x][y]=True# Directions: up, down, left, rightdx=[1,-1,0,0]dy=[0,0,1,-1]whileq:cx,cy=q.popleft()# Mark if the current land cell lies on the boundaryifcx==0orcy==0orcx==n-1orcy==m-1:hasBoundary[0]=True# Explore all 4 directionsfordirinrange(4):nx,ny=cx+dx[dir],cy+dy[dir]# Check boundaries and unvisited landif0<=nx<nand0<=ny<mandnotvisited[nx][ny]andmatrix[nx][ny]==1:visited[nx][ny]=Trueq.append((nx,ny))# Count the number of closed islandsdefclosedIsland(matrix):n,m=len(matrix),len(matrix[0])visited=[[Falsefor_inrange(m)]for_inrange(n)]result=0# Start DFS for land cells foriinrange(n):forjinrange(m):#Check it is land cell and not visitedifmatrix[i][j]==1andnotvisited[i][j]:hasBoundary=[False]dfs(matrix,visited,i,j,n,m,hasBoundary)# Count only if not touching boundaryifnothasBoundary[0]:result+=1returnresult#Driver Code Startsif__name__=="__main__":matrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]]print(closedIsland(matrix))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code Ends// BFS to mark all connected land cells as visitedstaticvoiddfs(int[,]matrix,bool[,]visited,intx,inty,intn,intm,refboolhasBoundary){Queue<(int,int)>q=newQueue<(int,int)>();q.Enqueue((x,y));visited[x,y]=true;// Directions: up, down, left, rightint[]dx={1,-1,0,0};int[]dy={0,0,1,-1};while(q.Count>0){var(cx,cy)=q.Dequeue();// Mark if the current land cell lies on the boundaryif(cx==0||cy==0||cx==n-1||cy==m-1)hasBoundary=true;// Explore all 4 directionsfor(intdir=0;dir<4;++dir){intnx=cx+dx[dir];intny=cy+dy[dir];// Check boundaries and unvisited landif(nx>=0&&ny>=0&&nx<n&&ny<m&&!visited[nx,ny]&&matrix[nx,ny]==1){visited[nx,ny]=true;q.Enqueue((nx,ny));}}}}// Count the number of closed islandsstaticintclosedIsland(int[,]matrix){intn=matrix.GetLength(0),m=matrix.GetLength(1);bool[,]visited=newbool[n,m];intresult=0;// Start DFS for land cells for(inti=0;i<n;++i){for(intj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i,j]==1&&!visited[i,j]){boolhasBoundary=false;dfs(matrix,visited,i,j,n,m,refhasBoundary);// Count only if not touching boundaryif(!hasBoundary)result++;}}}returnresult;}//Driver Code StartsstaticvoidMain(){int[,]matrix={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};Console.WriteLine(closedIsland(matrix));}}//Driver Code Ends
JavaScript
// BFS to mark all connected land cells as visitedfunctiondfs(matrix,visited,x,y,n,m,hasBoundary){constq=[];q.push([x,y]);visited[x][y]=true;// Directions: up, down, left, rightconstdx=[1,-1,0,0];constdy=[0,0,1,-1];while(q.length>0){const[cx,cy]=q.shift();// Mark if the current land cell lies on the boundaryif(cx===0||cy===0||cx===n-1||cy===m-1)hasBoundary.value=true;// Explore all 4 directionsfor(letdir=0;dir<4;++dir){constnx=cx+dx[dir];constny=cy+dy[dir];// Check boundaries and unvisited landif(nx>=0&&ny>=0&&nx<n&&ny<m&&!visited[nx][ny]&&matrix[nx][ny]===1){visited[nx][ny]=true;q.push([nx,ny]);}}}}// Count the number of closed islandsfunctionclosedIsland(matrix){constn=matrix.length,m=matrix[0].length;constvisited=Array.from({length:n},()=>Array(m).fill(false));letresult=0;// Start DFS for land cells for(leti=0;i<n;++i){for(letj=0;j<m;++j){//Check it is land cell and not visitedif(matrix[i][j]===1&&!visited[i][j]){consthasBoundary={value:false};dfs(matrix,visited,i,j,n,m,hasBoundary);// Count only if not touching boundaryif(!hasBoundary.value)result++;}}}returnresult;}//Driver Code//Driver Code Startsconstmatrix=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]];console.log(closedIsland(matrix));//Driver Code Ends
Output
2
[Approach – 4] Using Disjoint-Set ( Union-Find ) – O(N × M) Time and O(N × M) Space
The main idea is to use the Disjoint Set Union (DSU). Each land cell is treated as a node, and whenever two land cells are adjacent, they are joined into the same set using union operations. Land cells that touch the boundary are marked separately, since any group connected to the boundary cannot form a closed island. After processing the entire grid, the number of distinct sets (or parent nodes) that are not connected to the boundary gives the total number of closed islands.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<numeric>usingnamespacestd;//Driver Code EndsclassDSU{private:vector<int>parent;public:DSU(intn){parent.resize(n);iota(parent.begin(),parent.end(),0);}intfind(intx){while(x!=parent[x]){x=parent[x];}returnx;}voidunionFind(inta,intb){introotA=find(a);introotB=find(b);if(rootA!=rootB)parent[rootA]=rootB;}boolisRoot(intx){returnparent[x]==x;}};// DFS to mark all boundary-connected land cells as watervoidfloodFill(vector<vector<int>>&mat,intx,inty,intn,intm){if(x<0||y<0||x>=m||y>=n||mat[x][y]==0)return;// Mark as watermat[x][y]=0;floodFill(mat,x+1,y,n,m);floodFill(mat,x-1,y,n,m);floodFill(mat,x,y+1,n,m);floodFill(mat,x,y-1,n,m);}// Remove all land connected to the boundaryvoidremBoundIs(vector<vector<int>>&mat){intm=mat.size(),n=mat[0].size();for(inti=0;i<m;i++){for(intj=0;j<n;j++){// Check boundary cellsif(i*j==0||i==m-1||j==n-1){if(mat[i][j]==1){floodFill(mat,i,j,n,m);}}}}}// Count the number of closed islandsintclosedIsland(vector<vector<int>>&mat){if(mat.empty())return0;intm=mat.size(),n=mat[0].size();// Remove open islands connected to boundaryremBoundIs(mat);vector<pair<int,int>>edges;// Create edges for adjacent land cellsfor(inti=0;i<m;i++){for(intj=0;j<n;j++){if(mat[i][j]==1){intid=i*n+j;// Connect to right neighborif(j+1<n&&mat[i][j+1]==1)edges.push_back({id,id+1});// Connect to bottom neighborif(i+1<m&&mat[i+1][j]==1)edges.push_back({id,(i+1)*n+j});}}}// Initialize DSUDSUdsu(m*n);// Apply union operationsfor(auto&edge:edges){dsu.unionFind(edge.first,edge.second);}// Count number of closed islands (distinct root components)intcount=0;for(inti=0;i<m*n;i++){if(mat[i/n][i%n]==1&&dsu.isRoot(i))count++;}returncount;}//Driver Code Startsintmain(){vector<vector<int>>mat={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};cout<<closedIsland(mat);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;//Driver Code EndsclassDSU{privateint[]parent;publicDSU(intn){parent=newint[n];for(inti=0;i<n;i++)parent[i]=i;}publicintfind(intx){while(x!=parent[x]){x=parent[x];}returnx;}publicvoidunionFind(inta,intb){introotA=find(a);introotB=find(b);if(rootA!=rootB)parent[rootA]=rootB;}publicbooleanisRoot(intx){returnparent[x]==x;}}publicclassGFG{// DFS to mark all boundary-connected land cells as waterstaticvoidfloodFill(int[][]mat,intx,inty,intn,intm){if(x<0||y<0||x>=m||y>=n||mat[x][y]==0)return;// Mark as watermat[x][y]=0;floodFill(mat,x+1,y,n,m);floodFill(mat,x-1,y,n,m);floodFill(mat,x,y+1,n,m);floodFill(mat,x,y-1,n,m);}// Remove all land connected to the boundarystaticvoidremBoundIs(int[][]mat){intm=mat.length,n=mat[0].length;for(inti=0;i<m;i++){for(intj=0;j<n;j++){// Check boundary cellsif(i*j==0||i==m-1||j==n-1){if(mat[i][j]==1){floodFill(mat,i,j,n,m);}}}}}// Count the number of closed islandsstaticintclosedIsland(int[][]mat){if(mat.length==0)return0;intm=mat.length,n=mat[0].length;// Remove open islands connected to boundaryremBoundIs(mat);ArrayList<int[]>edges=newArrayList<>();// Create edges for adjacent land cellsfor(inti=0;i<m;i++){for(intj=0;j<n;j++){if(mat[i][j]==1){intid=i*n+j;// Connect to right neighborif(j+1<n&&mat[i][j+1]==1)edges.add(newint[]{id,id+1});// Connect to bottom neighborif(i+1<m&&mat[i+1][j]==1)edges.add(newint[]{id,(i+1)*n+j});}}}// Initialize DSUDSUdsu=newDSU(m*n);// Apply union operationsfor(int[]edge:edges){dsu.unionFind(edge[0],edge[1]);}// Count number of closed islands (distinct root components)intcount=0;for(inti=0;i<m*n;i++){if(mat[i/n][i%n]==1&&dsu.isRoot(i))count++;}returncount;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]mat={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};System.out.println(closedIsland(mat));}}//Driver Code Ends
Python
classDSU:def__init__(self,n):self.parent=list(range(n))deffind(self,x):whilex!=self.parent[x]:x=self.parent[x]returnxdefunionFind(self,a,b):rootA=self.find(a)rootB=self.find(b)ifrootA!=rootB:self.parent[rootA]=rootBdefisRoot(self,x):returnself.parent[x]==x# DFS to mark all boundary-connected land cells as waterdeffloodFill(mat,x,y,n,m):ifx<0ory<0orx>=mory>=normat[x][y]==0:return# Mark as watermat[x][y]=0floodFill(mat,x+1,y,n,m)floodFill(mat,x-1,y,n,m)floodFill(mat,x,y+1,n,m)floodFill(mat,x,y-1,n,m)# Remove all land connected to the boundarydefremBoundIs(mat):m,n=len(mat),len(mat[0])foriinrange(m):forjinrange(n):# Check boundary cellsifi*j==0ori==m-1orj==n-1:ifmat[i][j]==1:floodFill(mat,i,j,n,m)# Count the number of closed islandsdefclosedIsland(mat):ifnotmat:return0m,n=len(mat),len(mat[0])# Remove open islands connected to boundaryremBoundIs(mat)edges=[]# Create edges for adjacent land cellsforiinrange(m):forjinrange(n):ifmat[i][j]==1:id=i*n+j# Connect to right neighborifj+1<nandmat[i][j+1]==1:edges.append((id,id+1))# Connect to bottom neighborifi+1<mandmat[i+1][j]==1:edges.append((id,(i+1)*n+j))# Initialize DSUdsu=DSU(m*n)# Apply union operationsfora,binedges:dsu.unionFind(a,b)# Count number of closed islands (distinct root components)count=0foriinrange(m*n):ifmat[i//n][i%n]==1anddsu.isRoot(i):count+=1returncount#Driver Code Starts# Driver codemat=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]]print(closedIsland(mat))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;//Driver Code EndsclassDSU{privateint[]parent;publicDSU(intn){parent=newint[n];for(inti=0;i<n;i++)parent[i]=i;}publicintfind(intx){while(x!=parent[x]){x=parent[x];}returnx;}publicvoidunionFind(inta,intb){introotA=find(a);introotB=find(b);if(rootA!=rootB)parent[rootA]=rootB;}publicboolisRoot(intx){returnparent[x]==x;}}classGFG{// DFS to mark all boundary-connected land cells as waterstaticvoidfloodFill(int[,]mat,intx,inty,intn,intm){if(x<0||y<0||x>=m||y>=n||mat[x,y]==0)return;// Mark as watermat[x,y]=0;floodFill(mat,x+1,y,n,m);floodFill(mat,x-1,y,n,m);floodFill(mat,x,y+1,n,m);floodFill(mat,x,y-1,n,m);}// Remove all land connected to the boundarystaticvoidremBoundIs(int[,]mat){intm=mat.GetLength(0);intn=mat.GetLength(1);for(inti=0;i<m;i++){for(intj=0;j<n;j++){// Check boundary cellsif(i*j==0||i==m-1||j==n-1){if(mat[i,j]==1){floodFill(mat,i,j,n,m);}}}}}// Count the number of closed islandsstaticintclosedIsland(int[,]mat){intm=mat.GetLength(0);intn=mat.GetLength(1);if(m==0||n==0)return0;// Remove open islands connected to boundaryremBoundIs(mat);List<(int,int)>edges=newList<(int,int)>();// Create edges for adjacent land cellsfor(inti=0;i<m;i++){for(intj=0;j<n;j++){if(mat[i,j]==1){intid=i*n+j;// Connect to right neighborif(j+1<n&&mat[i,j+1]==1)edges.Add((id,id+1));// Connect to bottom neighborif(i+1<m&&mat[i+1,j]==1)edges.Add((id,(i+1)*n+j));}}}// Initialize DSUDSUdsu=newDSU(m*n);// Apply union operationsforeach(varedgeinedges){dsu.unionFind(edge.Item1,edge.Item2);}// Count number of closed islands (distinct root components)intcount=0;for(inti=0;i<m*n;i++){intr=i/n,c=i%n;if(mat[r,c]==1&&dsu.isRoot(i))count++;}returncount;}//Driver Code StartsstaticvoidMain(){int[,]mat={{0,0,0,0,0,0,0,1},{0,1,1,1,1,0,0,1},{0,1,0,1,0,0,0,1},{0,1,1,1,1,0,1,0},{0,0,0,0,0,0,0,1}};Console.WriteLine(closedIsland(mat));}}//Driver Code Ends
JavaScript
classDSU{constructor(n){this.parent=Array.from({length:n},(_,i)=>i);}find(x){while(x!==this.parent[x]){x=this.parent[x];}returnx;}unionFind(a,b){constrootA=this.find(a);constrootB=this.find(b);if(rootA!==rootB)this.parent[rootA]=rootB;}isRoot(x){returnthis.parent[x]===x;}}// DFS to mark all boundary-connected land cells as waterfunctionfloodFill(mat,x,y,n,m){if(x<0||y<0||x>=m||y>=n||mat[x][y]===0)return;// Mark as watermat[x][y]=0;floodFill(mat,x+1,y,n,m);floodFill(mat,x-1,y,n,m);floodFill(mat,x,y+1,n,m);floodFill(mat,x,y-1,n,m);}// Remove all land connected to the boundaryfunctionremBoundIs(mat){constm=mat.length,n=mat[0].length;for(leti=0;i<m;i++){for(letj=0;j<n;j++){// Check boundary cellsif(i*j===0||i===m-1||j===n-1){if(mat[i][j]===1){floodFill(mat,i,j,n,m);}}}}}// Count the number of closed islandsfunctionclosedIsland(mat){if(mat.length===0)return0;constm=mat.length,n=mat[0].length;// Remove open islands connected to boundaryremBoundIs(mat);constedges=[];// Create edges for adjacent land cellsfor(leti=0;i<m;i++){for(letj=0;j<n;j++){if(mat[i][j]===1){constid=i*n+j;// Connect to right neighborif(j+1<n&&mat[i][j+1]===1)edges.push([id,id+1]);// Connect to bottom neighborif(i+1<m&&mat[i+1][j]===1)edges.push([id,(i+1)*n+j]);}}}// Initialize DSUconstdsu=newDSU(m*n);// Apply union operationsfor(const[a,b]ofedges){dsu.unionFind(a,b);}// Count number of closed islands (distinct root components)letcount=0;for(leti=0;i<m*n;i++){constr=Math.floor(i/n);constc=i%n;if(mat[r][c]===1&&dsu.isRoot(i))count++;}returncount;}// Example usage//Driver Code Startsconstmat=[[0,0,0,0,0,0,0,1],[0,1,1,1,1,0,0,1],[0,1,0,1,0,0,0,1],[0,1,1,1,1,0,1,0],[0,0,0,0,0,0,0,1]];console.log(closedIsland(mat));//Driver Code Ends