import java.util.ArrayList ;
class RectangularIslands {
/*
Count number of islands where every island is row-wise and column-wise separated
Given a rectangular matrix which has only two possible values ‘X’ and ‘O’. The values ‘X’ always appear in form of rectangular islands and these islands are always row-wise and column-wise separated by at least one line of ‘O’s. Note that islands can only be diagonally adjacent. Count the number of islands in the given matrix.
Examples:
mat[M][N] = {{'O', 'O', 'O'},
{'X', 'X', 'O'},
{'X', 'X', 'O'},
{'O', 'O', 'X'},
{'O', 'O', 'X'},
{'X', 'X', 'O'}
};
Output: Number of islands is 3
mat[M][N] = {{'X', 'O', 'O', 'O', 'O', 'O'},
{'X', 'O', 'X', 'X', 'X', 'X'},
{'O', 'O', 'O', 'O', 'O', 'O'},
{'X', 'X', 'X', 'O', 'X', 'X'},
{'X', 'X', 'X', 'O', 'X', 'X'},
{'O', 'O', 'O', 'O', 'X', 'X'},
};
Output: Number of islands is 4
*/
public static void main
( String [ ] args
) { char [ ] [ ] mat1 =
{ { 'O' , 'O' , 'O' } ,
{ 'X' , 'X' , 'O' } ,
{ 'X' , 'X' , 'O' } ,
{ 'O' , 'O' , 'X' } ,
{ 'O' , 'O' , 'X' } ,
{ 'X' , 'X' , 'O' }
} ;
findIslands( mat1) ;
char [ ] [ ] mat2 =
{ { 'X' , 'O' , 'O' , 'O' , 'O' , 'O' } ,
{ 'X' , 'O' , 'X' , 'X' , 'X' , 'X' } ,
{ 'O' , 'O' , 'O' , 'O' , 'O' , 'O' } ,
{ 'X' , 'X' , 'X' , 'O' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'O' , 'X' , 'X' } ,
{ 'O' , 'O' , 'O' , 'O' , 'X' , 'X' } ,
} ;
findIslands( mat2) ;
char [ ] [ ] mat3 =
{ { 'X' , 'O' , 'O' , 'O' , 'O' , 'O' } ,
{ 'O' , 'O' , 'X' , 'O' , 'X' , 'X' } ,
{ 'O' , 'O' , 'O' , 'O' , 'O' , 'O' } ,
{ 'X' , 'O' , 'X' , 'O' , 'X' , 'X' } ,
{ 'X' , 'O' , 'X' , 'O' , 'X' , 'X' } ,
{ 'O' , 'O' , 'O' , 'O' , 'X' , 'X' } ,
} ;
findIslands( mat3) ;
char [ ] [ ] mat4 =
{ { 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
{ 'X' , 'X' , 'X' , 'X' , 'X' , 'X' } ,
} ;
findIslands( mat4) ;
}
public static ArrayList< RectangularIslands.Island > islandList;
public static void findIslands( char [ ] [ ] matrix) {
islandList = new ArrayList< RectangularIslands.Island > ( ) ;
int i= 0 ,j= 0 ;
int matrixRows = matrix.length ;
int matrixCols = matrix[ 0 ] .length ;
while ( i< matrixRows) {
j= 0 ;
while ( j< matrixCols) {
if ( matrix[ i] [ j] == 'X' ) {
// Check if this position is already considered in previously observed island
Island notedIsland = isInIsland( i,j) ;
if ( notedIsland!= null ) {
// point is already in noted island. So directly jump to position outside island
j= notedIsland.endPointColnum + 1 ;
} else {
int startPointRownum = i;
int startPointColnum = j;
j++;
// We have found top-left corner of island. Now find the boundaries
while ( j< matrixCols && matrix[ i] [ j] == 'X' ) {
j++; // Keep moving right till we find X or end of matrix
}
int endPointColnum = j- 1 ; // Current j points to 'O' or matrix boundry
// Find the bottom of island
int k= i;
while ( k+ 1 < matrixRows && matrix[ k+ 1 ] [ startPointColnum] == 'X' ) {
// Keep moving right till we find X or end of matrix
k++;
}
int endPointRownum = k;
// Create rectangle object and add to list
Island ilnd = new Island( ) ;
ilnd.startPointRownum = startPointRownum;
ilnd.startPointColnum = startPointColnum;
ilnd.endPointRownum = endPointRownum;
ilnd.endPointColnum = endPointColnum;
islandList.add ( ilnd) ;
}
} else {
j++;
}
}
i++;
}
System .
out .
println ( "No of islands =" + islandList.
size ( ) ) ; }
static private class Island{
public int startPointRownum,startPointColnum,endPointRownum,endPointColnum;
}
public static Island isInIsland( int rownum, int colnum) {
for ( Island ilnd: islandList) {
if ( ilnd.startPointRownum <= rownum && ilnd.startPointColnum <= colnum && ilnd.endPointRownum >= rownum && ilnd.endPointColnum >= colnum) {
return ilnd;
}
}
return null ;
}
}
aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CgpjbGFzcyBSZWN0YW5ndWxhcklzbGFuZHMgewoKCS8qCkNvdW50IG51bWJlciBvZiBpc2xhbmRzIHdoZXJlIGV2ZXJ5IGlzbGFuZCBpcyByb3ctd2lzZSBhbmQgY29sdW1uLXdpc2Ugc2VwYXJhdGVkCkdpdmVuIGEgcmVjdGFuZ3VsYXIgbWF0cml4IHdoaWNoIGhhcyBvbmx5IHR3byBwb3NzaWJsZSB2YWx1ZXMg4oCYWOKAmSBhbmQg4oCYT+KAmS4gVGhlIHZhbHVlcyDigJhY4oCZIGFsd2F5cyBhcHBlYXIgaW4gZm9ybSBvZiByZWN0YW5ndWxhciBpc2xhbmRzIGFuZCB0aGVzZSBpc2xhbmRzIGFyZSBhbHdheXMgcm93LXdpc2UgYW5kIGNvbHVtbi13aXNlIHNlcGFyYXRlZCBieSBhdCBsZWFzdCBvbmUgbGluZSBvZiDigJhP4oCZcy4gTm90ZSB0aGF0IGlzbGFuZHMgY2FuIG9ubHkgYmUgZGlhZ29uYWxseSBhZGphY2VudC4gQ291bnQgdGhlIG51bWJlciBvZiBpc2xhbmRzIGluIHRoZSBnaXZlbiBtYXRyaXguCgpFeGFtcGxlczoKCm1hdFtNXVtOXSA9ICB7eydPJywgJ08nLCAnTyd9LAogICAgICAgICAgICAgIHsnWCcsICdYJywgJ08nfSwKICAgICAgICAgICAgICB7J1gnLCAnWCcsICdPJ30sCiAgICAgICAgICAgICAgeydPJywgJ08nLCAnWCd9LAogICAgICAgICAgICAgIHsnTycsICdPJywgJ1gnfSwKICAgICAgICAgICAgICB7J1gnLCAnWCcsICdPJ30KICAgICAgICAgICAgIH07Ck91dHB1dDogTnVtYmVyIG9mIGlzbGFuZHMgaXMgMwoKbWF0W01dW05dID0gIHt7J1gnLCAnTycsICdPJywgJ08nLCAnTycsICdPJ30sCiAgICAgICAgICAgICAgeydYJywgJ08nLCAnWCcsICdYJywgJ1gnLCAnWCd9LAogICAgICAgICAgICAgIHsnTycsICdPJywgJ08nLCAnTycsICdPJywgJ08nfSwKICAgICAgICAgICAgICB7J1gnLCAnWCcsICdYJywgJ08nLCAnWCcsICdYJ30sCiAgICAgICAgICAgICAgeydYJywgJ1gnLCAnWCcsICdPJywgJ1gnLCAnWCd9LAogICAgICAgICAgICAgIHsnTycsICdPJywgJ08nLCAnTycsICdYJywgJ1gnfSwKICAgICAgICAgICAgIH07Ck91dHB1dDogTnVtYmVyIG9mIGlzbGFuZHMgaXMgNAoJICovCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CgkJY2hhcltdW10gbWF0MSAgID0gIAoJCSAgICAge3snTycsICdPJywgJ08nfSwKICAgICAgICAgICAgIHsnWCcsICdYJywgJ08nfSwKICAgICAgICAgICAgIHsnWCcsICdYJywgJ08nfSwKICAgICAgICAgICAgIHsnTycsICdPJywgJ1gnfSwKICAgICAgICAgICAgIHsnTycsICdPJywgJ1gnfSwKICAgICAgICAgICAgIHsnWCcsICdYJywgJ08nfQogICAgICAgICAgICB9OwoJZmluZElzbGFuZHMobWF0MSk7CgkKCQljaGFyW11bXSBtYXQyID0gIAoJCQkgICAgIHt7J1gnLCAnTycsICdPJywgJ08nLCAnTycsICdPJ30sCgkgICAgICAgICAgICAgIHsnWCcsICdPJywgJ1gnLCAnWCcsICdYJywgJ1gnfSwKCSAgICAgICAgICAgICAgeydPJywgJ08nLCAnTycsICdPJywgJ08nLCAnTyd9LAoJICAgICAgICAgICAgICB7J1gnLCAnWCcsICdYJywgJ08nLCAnWCcsICdYJ30sCgkgICAgICAgICAgICAgIHsnWCcsICdYJywgJ1gnLCAnTycsICdYJywgJ1gnfSwKCSAgICAgICAgICAgICAgeydPJywgJ08nLCAnTycsICdPJywgJ1gnLCAnWCd9LAoJICAgICAgICAgICAgIH07CgkJZmluZElzbGFuZHMobWF0Mik7CgkJCgkJY2hhcltdW10gbWF0MyA9CgkJCQkgIHt7J1gnLCAnTycsICdPJywgJ08nLCAnTycsICdPJ30sCgkgICAgICAgICAgICAgIHsnTycsICdPJywgJ1gnLCAnTycsICdYJywgJ1gnfSwKCSAgICAgICAgICAgICAgeydPJywgJ08nLCAnTycsICdPJywgJ08nLCAnTyd9LAoJICAgICAgICAgICAgICB7J1gnLCAnTycsICdYJywgJ08nLCAnWCcsICdYJ30sCgkgICAgICAgICAgICAgIHsnWCcsICdPJywgJ1gnLCAnTycsICdYJywgJ1gnfSwKCSAgICAgICAgICAgICAgeydPJywgJ08nLCAnTycsICdPJywgJ1gnLCAnWCd9LAoJICAgICAgICAgICAgIH07CgkJZmluZElzbGFuZHMobWF0Myk7CgkJCgkJY2hhcltdW10gbWF0NCA9CgkJCSAge3snWCcsICdYJywgJ1gnLCAnWCcsICdYJywgJ1gnfSwKCQkJeydYJywgJ1gnLCAnWCcsICdYJywgJ1gnLCAnWCd9LAoJCQl7J1gnLCAnWCcsICdYJywgJ1gnLCAnWCcsICdYJ30sCgkJCXsnWCcsICdYJywgJ1gnLCAnWCcsICdYJywgJ1gnfSwKCQkJeydYJywgJ1gnLCAnWCcsICdYJywgJ1gnLCAnWCd9LAoJCQl7J1gnLCAnWCcsICdYJywgJ1gnLCAnWCcsICdYJ30sCiAgICAgICAgICAgfTsKCWZpbmRJc2xhbmRzKG1hdDQpOwoKCX0KCQoJCglwdWJsaWMgc3RhdGljIEFycmF5TGlzdDxSZWN0YW5ndWxhcklzbGFuZHMuSXNsYW5kPiBpc2xhbmRMaXN0OwoJcHVibGljIHN0YXRpYyB2b2lkIGZpbmRJc2xhbmRzKGNoYXJbXVtdIG1hdHJpeCkgewoJCWlzbGFuZExpc3QgPSBuZXcgQXJyYXlMaXN0PFJlY3Rhbmd1bGFySXNsYW5kcy5Jc2xhbmQ+KCk7CgkJCgkJaW50IGk9MCxqPTA7CgkJaW50IG1hdHJpeFJvd3MgPSBtYXRyaXgubGVuZ3RoOwoJCWludCBtYXRyaXhDb2xzID0gbWF0cml4WzBdLmxlbmd0aDsKCQkKCQl3aGlsZShpPG1hdHJpeFJvd3MpewoJCQlqPTA7CgkJCXdoaWxlKGo8bWF0cml4Q29scyl7CgkJCQlpZihtYXRyaXhbaV1bal0gPT0nWCcpewoJCQkJCS8vIENoZWNrIGlmIHRoaXMgcG9zaXRpb24gaXMgYWxyZWFkeSBjb25zaWRlcmVkIGluIHByZXZpb3VzbHkgb2JzZXJ2ZWQgaXNsYW5kCgkJCQkJSXNsYW5kIG5vdGVkSXNsYW5kID0gIGlzSW5Jc2xhbmQoaSxqKTsKCQkJCQlpZihub3RlZElzbGFuZCE9bnVsbCl7CgkJCQkJCS8vIHBvaW50IGlzIGFscmVhZHkgaW4gbm90ZWQgaXNsYW5kLiBTbyBkaXJlY3RseSBqdW1wIHRvIHBvc2l0aW9uIG91dHNpZGUgaXNsYW5kCgkJCQkJCWo9bm90ZWRJc2xhbmQuZW5kUG9pbnRDb2xudW0rMTsKCQkJCQl9ZWxzZXsKCQkJCQkJaW50IHN0YXJ0UG9pbnRSb3dudW0gPSBpOwoJCQkJCQlpbnQgc3RhcnRQb2ludENvbG51bSA9IGo7CgkJCQkJCWorKzsKCQkJCQkJLy8gV2UgaGF2ZSBmb3VuZCB0b3AtbGVmdCBjb3JuZXIgb2YgaXNsYW5kLiBOb3cgZmluZCB0aGUgYm91bmRhcmllcwoJCQkJCQl3aGlsZShqPG1hdHJpeENvbHMgJiYgbWF0cml4W2ldW2pdPT0nWCcpewoJCQkJCQkJaisrOyAvLyBLZWVwIG1vdmluZyByaWdodCB0aWxsIHdlIGZpbmQgWCBvciBlbmQgb2YgbWF0cml4CgkJCQkJCX0KCQkJCQkJaW50IGVuZFBvaW50Q29sbnVtID0gai0xOyAvLyBDdXJyZW50IGogcG9pbnRzIHRvICdPJyBvciBtYXRyaXggYm91bmRyeQoJCQkJCQoJCQkJCQkvLyBGaW5kIHRoZSBib3R0b20gb2YgaXNsYW5kIAoJCQkJCQlpbnQgaz1pOwoJCQkJCQl3aGlsZShrKzE8bWF0cml4Um93cyAmJiBtYXRyaXhbaysxXVtzdGFydFBvaW50Q29sbnVtXT09J1gnKXsKCQkJCQkJCS8vIEtlZXAgbW92aW5nIHJpZ2h0IHRpbGwgd2UgZmluZCBYIG9yIGVuZCBvZiBtYXRyaXgKCQkJCQkJCWsrKzsKCQkJCQkJfQoJCQkJCQlpbnQgZW5kUG9pbnRSb3dudW0gPSBrOwoJCQkJCQoJCQkJCQkvLyBDcmVhdGUgcmVjdGFuZ2xlIG9iamVjdCBhbmQgYWRkIHRvIGxpc3QKCQkJCQkJSXNsYW5kIGlsbmQgPSBuZXcgSXNsYW5kKCk7CgkJCQkJCWlsbmQuc3RhcnRQb2ludFJvd251bT1zdGFydFBvaW50Um93bnVtOwoJCQkJCQlpbG5kLnN0YXJ0UG9pbnRDb2xudW09c3RhcnRQb2ludENvbG51bTsKCQkJCQkJaWxuZC5lbmRQb2ludFJvd251bT1lbmRQb2ludFJvd251bTsKCQkJCQkJaWxuZC5lbmRQb2ludENvbG51bT1lbmRQb2ludENvbG51bTsKCQkJCQkJaXNsYW5kTGlzdC5hZGQoaWxuZCk7CgkJCQkJfQoJCQkJfWVsc2V7CgkJCQkJaisrOwoJCQkJfQoJCQl9CgkJCWkrKzsKCQl9CgkJCgkJU3lzdGVtLm91dC5wcmludGxuKCJObyBvZiBpc2xhbmRzID0iK2lzbGFuZExpc3Quc2l6ZSgpKTsKCX0KCXN0YXRpYyBwcml2YXRlIGNsYXNzIElzbGFuZHsKCQlwdWJsaWMgaW50IHN0YXJ0UG9pbnRSb3dudW0sc3RhcnRQb2ludENvbG51bSxlbmRQb2ludFJvd251bSxlbmRQb2ludENvbG51bTsKCX0KCQoJcHVibGljIHN0YXRpYyBJc2xhbmQgaXNJbklzbGFuZChpbnQgcm93bnVtLCBpbnQgY29sbnVtKXsKCQlmb3IoSXNsYW5kIGlsbmQ6aXNsYW5kTGlzdCl7CgkJCWlmKGlsbmQuc3RhcnRQb2ludFJvd251bTw9cm93bnVtICYmIGlsbmQuc3RhcnRQb2ludENvbG51bTw9Y29sbnVtICYmIGlsbmQuZW5kUG9pbnRSb3dudW0+PXJvd251bSAmJiBpbG5kLmVuZFBvaW50Q29sbnVtPj1jb2xudW0pewoJCQkJcmV0dXJuIGlsbmQ7CgkJCX0KCQl9CgkJcmV0dXJuIG51bGw7Cgl9Cgp9Cg==