Find the number of distinct islands in a 2D matrix
Last Updated : 13 Oct, 2026
Given a grid grid[][] of size n × m, consisting of characters 'L' and 'W', where 'L' represents Land and 'W' represents Water, find the number of distinct islands in the grid. An island is a group of one or more land cells connected horizontally or vertically.
Two islands are considered distinct if their shapes are different.
Two islands have the same shape if one can be translated to match the other exactly. Rotation and reflection are not allowed.
Examples:
Input: grid[][] = [['L', 'L', 'W', 'W', 'W'], ['L', 'L', 'W', 'W', 'W'], ['W', 'W', 'W', 'L', 'L'], ['W', 'W', 'W', 'L', 'L']] Output: 1 Explanation: The grid contains two islands. Both islands have the same shape (a 2 × 2 block of land), so they are counted as a single distinct island.
Input: grid[][] = [['L', 'L', 'W', 'L', 'L'], ['L', 'W', 'W', 'W', 'W'], ['W', 'W', 'W', 'W', 'L'], ['L', 'L', 'W', 'L', 'L']] Output: 3 Explanation: There are four islands in the grid. Two islands have the same shape, while the other two have different shapes. Therefore, the number of distinct island shapes is 3.
[Naive Approach] Compare Island Shapes - O((n × m)^2) Time and O(n × m) Space
The idea is to find every island using DFS and store its shape as relative coordinates.
For each island, record the coordinates of its land cells relative to its starting cell.
Compare the resulting shape with all previously stored shapes.
If no matching shape exists, store it as a new distinct shape.
C++
#include<bits/stdc++.h>usingnamespacestd;voiddfs(vector<vector<char>>&grid,intbaseRow,intbaseCol,introw,intcol,vector<pair<int,int>>&shape){intn=grid.size();intm=grid[0].size();if(row<0||row>=n||col<0||col>=m||grid[row][col]!='L'){return;}// Mark current cell as visitedgrid[row][col]='#';// Store relative coordinatesshape.push_back({row-baseRow,col-baseCol});dfs(grid,baseRow,baseCol,row-1,col,shape);dfs(grid,baseRow,baseCol,row+1,col,shape);dfs(grid,baseRow,baseCol,row,col-1,shape);dfs(grid,baseRow,baseCol,row,col+1,shape);}intcountDistinctIslands(vector<vector<char>>&grid){intn=grid.size();intm=grid[0].size();// Stores all distinct island shapesvector<vector<pair<int,int>>>distinctShapes;for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(grid[i][j]=='L'){vector<pair<int,int>>shape;// Find shape of current islanddfs(grid,i,j,i,j,shape);boolfound=false;// Compare with previously found shapesfor(auto&prevShape:distinctShapes){if(prevShape==shape){found=true;break;}}// Store shape if it is uniqueif(!found){distinctShapes.push_back(shape);}}}}returndistinctShapes.size();}// Driver Codeintmain(){intn=4,m=5;vector<vector<char>>grid={{'L','W','W','L','W'},{'L','W','W','L','W'},{'W','W','W','L','L'},{'L','L','W','W','W'}};cout<<countDistinctIslands(grid);return0;}
Java
importjava.util.ArrayList;classGFG{staticvoiddfs(char[][]grid,intbaseRow,intbaseCol,introw,intcol,ArrayList<String>shape){intn=grid.length;intm=grid[0].length;if(row<0||row>=n||col<0||col>=m||grid[row][col]!='L'){return;}// Mark current cell as visitedgrid[row][col]='#';// Store relative coordinatesshape.add((row-baseRow)+","+(col-baseCol));dfs(grid,baseRow,baseCol,row-1,col,shape);dfs(grid,baseRow,baseCol,row+1,col,shape);dfs(grid,baseRow,baseCol,row,col-1,shape);dfs(grid,baseRow,baseCol,row,col+1,shape);}staticintcountDistinctIslands(char[][]grid){intn=grid.length;intm=grid[0].length;// Stores all distinct island shapesArrayList<ArrayList<String>>distinctShapes=newArrayList<>();for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(grid[i][j]=='L'){ArrayList<String>shape=newArrayList<>();// Find shape of current islanddfs(grid,i,j,i,j,shape);booleanfound=false;// Compare with previously found shapesfor(ArrayList<String>prevShape:distinctShapes){if(prevShape.equals(shape)){found=true;break;}}// Store shape if it is uniqueif(!found){distinctShapes.add(shape);}}}}returndistinctShapes.size();}publicstaticvoidmain(String[]args){intn=4,m=5;char[][]grid={{'L','W','W','L','W'},{'L','W','W','L','W'},{'W','W','W','L','L'},{'L','L','W','W','W'}};System.out.println(countDistinctIslands(grid));}}
Python
defdfs(grid,baseRow,baseCol,row,col,shape):n=len(grid)m=len(grid[0])ifrow<0orrow>=norcol<0orcol>=morgrid[row][col]!='L':return# Mark current cell as visitedgrid[row][col]='#'# Store relative coordinatesshape.append((row-baseRow,col-baseCol))dfs(grid,baseRow,baseCol,row-1,col,shape)dfs(grid,baseRow,baseCol,row+1,col,shape)dfs(grid,baseRow,baseCol,row,col-1,shape)dfs(grid,baseRow,baseCol,row,col+1,shape)defcountDistinctIslands(grid):n=len(grid)m=len(grid[0])# Stores all distinct island shapesdistinctShapes=[]foriinrange(n):forjinrange(m):ifgrid[i][j]=='L':shape=[]# Find shape of current islanddfs(grid,i,j,i,j,shape)found=False# Compare with previously found shapesforprevShapeindistinctShapes:ifprevShape==shape:found=Truebreak# Store shape if it is uniqueifnotfound:distinctShapes.append(shape)returnlen(distinctShapes)if__name__=="__main__":n,m=4,5grid=[['L','W','W','L','W'],['L','W','W','L','W'],['W','W','W','L','L'],['L','L','W','W','W']]print(countDistinctIslands(grid))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticvoiddfs(char[,]grid,intbaseRow,intbaseCol,introw,intcol,List<string>shape){intn=grid.GetLength(0);intm=grid.GetLength(1);if(row<0||row>=n||col<0||col>=m||grid[row,col]!='L'){return;}// Mark current cell as visitedgrid[row,col]='#';// Store relative coordinatesshape.Add((row-baseRow)+","+(col-baseCol));// 4-direction DFSdfs(grid,baseRow,baseCol,row-1,col,shape);dfs(grid,baseRow,baseCol,row+1,col,shape);dfs(grid,baseRow,baseCol,row,col-1,shape);dfs(grid,baseRow,baseCol,row,col+1,shape);}staticintcountDistinctIslands(char[,]grid){intn=grid.GetLength(0);intm=grid.GetLength(1);// Stores all distinct island shapesList<List<string>>distinctShapes=newList<List<string>>();for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(grid[i,j]=='L'){List<string>shape=newList<string>();// Find shape of current islanddfs(grid,i,j,i,j,shape);boolfound=false;// Compare with previously stored shapesforeach(List<string>prevShapeindistinctShapes){if(prevShape.Count!=shape.Count){continue;}boolsame=true;for(intk=0;k<shape.Count;k++){if(prevShape[k]!=shape[k]){same=false;break;}}if(same){found=true;break;}}// Store shape if it is uniqueif(!found){distinctShapes.Add(shape);}}}}returndistinctShapes.Count;}staticvoidMain(){char[,]grid={{'L','W','W','L','W'},{'L','W','W','L','W'},{'W','W','W','L','L'},{'L','L','W','W','W'}};Console.WriteLine(countDistinctIslands(grid));}}
JavaScript
functiondfs(grid,baseRow,baseCol,row,col,shape){letn=grid.length;letm=grid[0].length;if(row<0||row>=n||col<0||col>=m||grid[row][col]!=="L"){return;}// Mark current cell as visitedgrid[row][col]="#";// Store relative coordinatesshape.push([row-baseRow,col-baseCol]);dfs(grid,baseRow,baseCol,row-1,col,shape);dfs(grid,baseRow,baseCol,row+1,col,shape);dfs(grid,baseRow,baseCol,row,col-1,shape);dfs(grid,baseRow,baseCol,row,col+1,shape);}functioncountDistinctIslands(grid){letn=grid.length;letm=grid[0].length;// Stores all distinct island shapesletdistinctShapes=[];for(leti=0;i<n;i++){for(letj=0;j<m;j++){if(grid[i][j]==="L"){letshape=[];// Find shape of current islanddfs(grid,i,j,i,j,shape);letfound=false;// Compare with previously found shapesfor(letprevShapeofdistinctShapes){if(JSON.stringify(prevShape)===JSON.stringify(shape)){found=true;break;}}// Store shape if it is uniqueif(!found){distinctShapes.push(shape);}}}}returndistinctShapes.length;}// Driver codeletgrid=[["L","W","W","L","W"],["L","W","W","L","W"],["W","W","W","L","L"],["L","L","W","W","W"]];console.log(countDistinctIslands(grid));
Output
3
[Expected Approach] Set - O(n × m) Time and O(n × m) Space
We store island shapes in a set, which keeps only unique shapes.
Each island is represented using the relative coordinates of its cells with respect to its first cell. Therefore, islands with the same shape produce the same representation, regardless of their position in the grid.
Consider the grid[][]:
The island starting at (0, 0) has relative coordinates [(0, 0), (0, 1), (1, 0)]. Insert this shape into the set.
The island starting at (0, 3) has relative coordinates [(0, 0), (0, 1)]. Insert this shape into the set.
The island starting at (2, 4) has relative coordinates [(0, 0), (1, -1), (1, 0)]. Since this shape differs from the existing shapes, insert it into the set.
The island starting at (3, 0) has relative coordinates [(0, 0), (0, 1)]. This shape already exists, so do not count it again.
After traversing the entire grid, the set contains 3 distinct island shapes.
C++
#include<bits/stdc++.h>usingnamespacestd;vector<vector<int>>dirs={{0,-1},{-1,0},{0,1},{1,0}};voiddfs(vector<vector<char>>&grid,intx0,inty0,inti,intj,vector<pair<int,int>>&shape){introws=grid.size(),cols=grid[0].size();if(i<0||i>=rows||j<0||j>=cols||grid[i][j]!='L')return;// Mark as visitedgrid[i][j]='#';// Store position relative to the starting cellshape.push_back({i-x0,j-y0});for(auto&dir:dirs){dfs(grid,x0,y0,i+dir[0],j+dir[1],shape);}}intcountDistinctIslands(vector<vector<char>>&grid){introws=grid.size();intcols=grid[0].size();set<vector<pair<int,int>>>shapes;for(inti=0;i<rows;i++){for(intj=0;j<cols;j++){if(grid[i][j]!='L')continue;vector<pair<int,int>>shape;dfs(grid,i,j,i,j,shape);shapes.insert(shape);}}return(int)shapes.size();}// Driver Codeintmain(){intn=4,m=5;vector<vector<char>>grid={{'L','L','W','L','L'},{'L','W','W','W','W'},{'W','W','W','W','L'},{'L','L','W','L','L'}};cout<<countDistinctIslands(grid);return0;}
Java
importjava.util.ArrayList;importjava.util.HashSet;importjava.util.Set;classGFG{staticint[][]dirs={{0,-1},{-1,0},{0,1},{1,0}};staticvoiddfs(char[][]grid,intx0,inty0,inti,intj,ArrayList<String>shape){introws=grid.length,cols=grid[0].length;if(i<0||i>=rows||j<0||j>=cols||grid[i][j]!='L')return;// Mark as visitedgrid[i][j]='#';// Store position relative to the starting cellshape.add((i-x0)+","+(j-y0));for(int[]dir:dirs){dfs(grid,x0,y0,i+dir[0],j+dir[1],shape);}}staticintcountDistinctIslands(char[][]grid){introws=grid.length;intcols=grid[0].length;Set<ArrayList<String>>shapes=newHashSet<>();for(inti=0;i<rows;i++){for(intj=0;j<cols;j++){if(grid[i][j]!='L')continue;ArrayList<String>shape=newArrayList<>();dfs(grid,i,j,i,j,shape);shapes.add(shape);}}returnshapes.size();}publicstaticvoidmain(String[]args){intn=4,m=5;char[][]grid={{'L','L','W','L','L'},{'L','W','W','W','W'},{'W','W','W','W','L'},{'L','L','W','L','L'}};System.out.println(countDistinctIslands(grid));}}
Python
defcountDistinctIslands(grid):rows=len(grid)cols=len(grid[0])# Four directions:# left, up, right, downdirs=[(0,-1),(-1,0),(0,1),(1,0)]# Store distinct island shapesshapes=set()foriinrange(rows):forjinrange(cols):ifgrid[i][j]!='L':continueshape=[]# DFS stackstack=[(i,j)]# Mark starting cell as visitedgrid[i][j]='#'whilestack:x,y=stack.pop()# Store relative coordinatesshape.append((x-i,y-j))fordx,dyindirs:nx=x+dxny=y+dyif(0<=nx<rowsand0<=ny<colsandgrid[nx][ny]=='L'):grid[nx][ny]='#'stack.append((nx,ny))# Store unique island shapeshapes.add(tuple(shape))returnlen(shapes)if__name__=="__main__":n=4m=5grid=[['L','L','W','L','L'],['L','W','W','W','W'],['W','W','W','W','L'],['L','L','W','L','L']]print(countDistinctIslands(grid))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Four directions:// left, up, right, downstaticint[][]dirs={newint[]{0,-1},newint[]{-1,0},newint[]{0,1},newint[]{1,0}};// DFS to traverse an island and// record its relative shapestaticvoiddfs(char[,]grid,intx0,inty0,inti,intj,List<(int,int)>shape){introws=grid.GetLength(0);intcols=grid.GetLength(1);if(i<0||i>=rows||j<0||j>=cols||grid[i,j]!='L')return;// Mark current cell as visitedgrid[i,j]='#';// Store relative coordinatesshape.Add((i-x0,j-y0));foreach(int[]dirindirs){dfs(grid,x0,y0,i+dir[0],j+dir[1],shape);}}staticintcountDistinctIslands(char[,]grid){introws=grid.GetLength(0);intcols=grid.GetLength(1);// Store distinct island shapesHashSet<string>shapes=newHashSet<string>();for(inti=0;i<rows;i++){for(intj=0;j<cols;j++){if(grid[i,j]!='L')continue;List<(int,int)>shape=newList<(int,int)>();// Find shape of current islanddfs(grid,i,j,i,j,shape);// Convert shape into a unique stringstringshapeKey=string.Join("|",shape.ConvertAll(p=>p.Item1+","+p.Item2));// Store unique shapeshapes.Add(shapeKey);}}returnshapes.Count;}staticvoidMain(){char[,]grid={{'L','L','W','L','L'},{'L','W','W','W','W'},{'W','W','W','W','L'},{'L','L','W','L','L'}};Console.WriteLine(countDistinctIslands(grid));}}
JavaScript
functiondfs(grid,x0,y0,i,j,shape,dirs){varrows=grid.length;varcols=grid[0].length;if(i<0||i>=rows||j<0||j>=cols||grid[i][j]!=="L"){return;}// Mark the current cell as visited.grid[i][j]="#";// Store coordinates relative to// the starting cell of the island.shape.push((i-x0)+","+(j-y0));for(vark=0;k<dirs.length;k++){vardx=dirs[k][0];vardy=dirs[k][1];dfs(grid,x0,y0,i+dx,j+dy,shape,dirs);}}functioncountDistinctIslands(grid){// Four possible directions:// left, up, right, downvardirs=[[0,-1],[-1,0],[0,1],[1,0]];varrows=grid.length;varcols=grid[0].length;// Stores the normalized shape of each island.varshapes={};for(vari=0;i<rows;i++){for(varj=0;j<cols;j++){if(grid[i][j]!=="L")continue;varshape=[];dfs(grid,i,j,i,j,shape,dirs);// Convert the shape into a unique string// representation and insert into the set.shapes[shape.join("|")]=true;}}returnObject.keys(shapes).length;}// Driver Codevargrid=[["L","L","W","L","L"],["L","W","W","W","W"],["W","W","W","W","L"],["L","L","W","L","L"]];console.log(countDistinctIslands(grid));