Given a boolean 2D matrix. The task is to find the number of distinct islands where a group of connected 1s (horizontally or vertically) forms an island. Two islands are considered to be distinct if and only if one island is equal to another (not rotated or reflected).
Examples:
Input: grid[][] =
{{1, 1, 0, 0, 0},
1, 1, 0, 0, 0},
0, 0, 0, 1, 1},
0, 0, 0, 1, 1}}
Output: 1
Island 1, 1 at the top left corner is same as island 1, 1 at the bottom right corner
Input: grid[][] =
{{1, 1, 0, 1, 1},
1, 0, 0, 0, 0},
0, 0, 0, 0, 1},
1, 1, 0, 1, 1}}
Output: 3
Distinct islands in the example above are 1, 1 at the top left corner; 1, 1 at the top right corner and 1 at the bottom right corner. We ignore the island 1, 1 at the bottom left corner since 1, 1 it is identical to the top right corner.
Approach: This problem is an extension of the problem Number of Islands.
The core of the question is to know if 2 islands are equal. The primary criteria is that the number of 1’s should be same in both. But this cannot be the only criteria as we have seen in example 2 above. So how do we know? We could use the position/coordinates of the 1’s.
If we take the first coordinates of any island as a base point and then compute the coordinates of other points from the base point, we can eliminate duplicates to get the distinct count of islands. So, using this approach, the coordinates for the 2 islands in example 1 above can be represented as: [(0, 0), (0, 1), (1, 0), (1, 1)].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector<vector< int > > dirs = { { 0, -1 },
{ -1, 0 },
{ 0, 1 },
{ 1, 0 } };
void dfs(vector<vector< int > >& grid, int x0, int y0,
int i, int j, vector<pair< int , int > >& v)
{
int rows = grid.size(), cols = grid[0].size();
if (i < 0 || i >= rows || j < 0
|| j >= cols || grid[i][j] <= 0)
return ;
grid[i][j] *= -1;
v.push_back({ i - x0, j - y0 });
for ( auto dir : dirs) {
dfs(grid, x0, y0, i + dir[0], j + dir[1], v);
}
}
int countDistinctIslands(vector<vector< int > >& grid)
{
int rows = grid.size();
if (rows == 0)
return 0;
int cols = grid[0].size();
if (cols == 0)
return 0;
set<vector<pair< int , int > > > coordinates;
for ( int i = 0; i < rows; ++i) {
for ( int j = 0; j < cols; ++j) {
if (grid[i][j] != 1)
continue ;
vector<pair< int , int > > v;
dfs(grid, i, j, i, j, v);
coordinates.insert(v);
}
}
return coordinates.size();
}
int main()
{
vector<vector< int > > grid = { { 1, 1, 0, 1, 1 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1 },
{ 1, 1, 0, 1, 1 } };
cout << "Number of distinct islands is "
<< countDistinctIslands(grid);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static void main(String[] args)
{
int [][] grid = { { 1 , 1 , 0 , 1 , 1 },
{ 1 , 0 , 0 , 0 , 0 },
{ 0 , 0 , 0 , 0 , 1 },
{ 1 , 1 , 0 , 1 , 1 }
};
System.out.println( "Number of distinct islands is " + countDistinctIslands(grid));
}
static int [][] dirs = { { 0 , - 1 },
{ - 1 , 0 },
{ 0 , 1 },
{ 1 , 0 }
};
private static String toString( int r, int c) {
return Integer.toString(r) + " " + Integer.toString(c);
}
private static void dfs( int [][] grid, int x0, int y0, int i, int j, ArrayList<String>v) {
int rows = grid.length, cols = grid[ 0 ].length;
if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] <= 0 )
return ;
grid[i][j] *= - 1 ;
v.add(toString(i - x0, j - y0));
for ( int k = 0 ; k < 4 ; k++) {
dfs(grid, x0, y0, i + dirs[k][ 0 ], j + dirs[k][ 1 ], v);
}
}
public static int countDistinctIslands( int [][] grid) {
int rows = grid.length;
if (rows == 0 )
return 0 ;
int cols = grid[ 0 ].length;
if (cols == 0 )
return 0 ;
HashSet<ArrayList<String>> coordinates = new HashSet<> ();
for ( int i = 0 ; i < rows; ++i) {
for ( int j = 0 ; j < cols; ++j) {
if (grid[i][j] != 1 )
continue ;
ArrayList<String> v = new ArrayList<>();
dfs(grid, i, j, i, j, v);
coordinates.add(v);
}
}
return coordinates.size();
}
}
|
Python3
dirs = [ [ 0 , - 1 ],
[ - 1 , 0 ],
[ 0 , 1 ],
[ 1 , 0 ] ]
def dfs(grid, x0, y0, i, j, v):
rows = len (grid)
cols = len (grid[ 0 ])
if i < 0 or i > = rows or j < 0 or j > = cols or grid[i][j] < = 0 :
return
grid[i][j] * = - 1
v.append( (i - x0, j - y0) )
for dir in dirs:
dfs(grid, x0, y0, i + dir [ 0 ], j + dir [ 1 ], v)
def countDistinctIslands(grid):
rows = len (grid)
if rows = = 0 :
return 0
cols = len (grid[ 0 ])
if cols = = 0 :
return 0
coordinates = set ()
for i in range (rows):
for j in range (cols):
if grid[i][j] ! = 1 :
continue
v = []
dfs(grid, i, j, i, j, v)
coordinates.add( tuple (v))
return len (coordinates)
grid = [[ 1 , 1 , 0 , 1 , 1 ],
[ 1 , 0 , 0 , 0 , 0 ],
[ 0 , 0 , 0 , 0 , 1 ],
[ 1 , 1 , 0 , 1 , 1 ] ]
print ( "Number of distinct islands is" , countDistinctIslands(grid))
|
C#
using System;
using System.Collections.Generic;
class GFG {
public static void Main( string [] args)
{
int [][] grid = { new int [] { 1, 1, 0, 1, 1 },
new int [] { 1, 0, 0, 0, 0 },
new int [] { 0, 0, 0, 0, 1 },
new int [] { 1, 1, 0, 1, 1 }
};
Console.WriteLine( "Number of distinct islands is " + CountDistinctIslands(grid));
}
static int [][] dirs = { new int [] { 0, -1 },
new int [] { -1, 0 },
new int [] { 0, 1 },
new int [] { 1, 0 }
};
private static string ToString( int r, int c) {
return r.ToString() + " " + c.ToString();
}
private static void Dfs( int [][] grid, int x0, int y0, int i, int j, List< string > v) {
int rows = grid.Length, cols = grid[0].Length;
if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] <= 0)
return ;
grid[i][j] *= -1;
v.Add(ToString(i - x0, j - y0));
for ( int k = 0; k < 4; k++) {
Dfs(grid, x0, y0, i + dirs[k][0], j + dirs[k][1], v);
}
}
public static int CountDistinctIslands( int [][] grid) {
int rows = grid.Length;
if (rows == 0)
return 0;
int cols = grid[0].Length;
if (cols == 0)
return 0;
HashSet<List< string >> coordinates = new HashSet<List< string >>();
for ( int i = 0; i < rows; ++i) {
for ( int j = 0; j < cols; ++j) {
if (grid[i][j] != 1)
continue ;
List< string > v = new List< string >();
Dfs(grid, i, j, i, j, v);
coordinates.Add(v);
}
}
return coordinates.Count-1;
}
}
|
Javascript
const dirs = [
[0, -1],
[-1, 0],
[0, 1],
[1, 0]
];
function dfs(grid, x0, y0, i, j, v) {
const rows = grid.length;
const cols = grid[0].length;
if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] <= 0) {
return ;
}
grid[i][j] *= -1;
v.push([i - x0, j - y0]);
for (const dir of dirs) {
dfs(grid, x0, y0, i + dir[0], j + dir[1], v);
}
}
function countDistinctIslands(grid) {
const rows = grid.length;
if (rows === 0) {
return 0;
}
const cols = grid[0].length;
if (cols === 0) {
return 0;
}
const coordinates = new Set();
for (let i = 0; i < rows; ++i) {
for (let j = 0; j < cols; ++j) {
if (grid[i][j] !== 1) {
continue ;
}
const v = [];
dfs(grid, i, j, i, j, v);
coordinates.add(JSON.stringify(v));
}
}
return coordinates.size;
}
const grid = [
[1, 1, 0, 1, 1],
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[1, 1, 0, 1, 1]
];
console.log( "Number of distinct islands is " , countDistinctIslands(grid));
|
Output: Number of distinct islands is 3
Time complexity: O(rows * cols * log(rows * cols))
Where rows is the number of rows and cols is the number of columns in the matrix, here we visit every cell so O(row * col) for that and for every cell we need to add atmost (row * col) pairs in set which will cost us O(log(rows*cols)) so overall time complexity will be O(rows * cols * log(rows * cols))
Auxiliary Space: O(rows * cols)
In set we need to ad atmost rows*cols entry so space complexity will be O(rows * cols)