1- # An island in matrix is a group of linked areas, all having the same value.
2- # This code counts number of islands in a given matrix, with including diagonal
3- # connections.
1+ class Matrix :
2+ """
3+ Class to represent a 2D grid as a matrix and count the number of islands.
4+ An island is a group of connected 1s (connections can be vertical, horizontal, or diagonal).
5+ """
46
5-
6- class Matrix : # Public class to implement a graph
77 def __init__ (self , row : int , col : int , graph : list [list [bool ]]) -> None :
8+ """
9+ Initialize the matrix.
10+
11+ :param row: Number of rows
12+ :param col: Number of columns
13+ :param graph: 2D list representing the matrix (1 = land, 0 = water)
14+
15+ >>> graph = [[1, 1, 0], [0, 1, 0], [1, 0, 0]]
16+ >>> m = Matrix(3, 3, graph)
17+ >>> m.ROW
18+ 3
19+ >>> m.COL
20+ 3
21+ >>> m.graph == graph
22+ True
23+
24+ # Edge case: Empty matrix
25+ >>> empty = Matrix(0, 0, [])
26+ >>> empty.ROW
27+ 0
28+ >>> empty.COL
29+ 0
30+ >>> empty.graph
31+ []
32+
33+ # Edge case: 1x1 matrix
34+ >>> single = Matrix(1, 1, [[1]])
35+ >>> single.ROW
36+ 1
37+ >>> single.COL
38+ 1
39+ >>> single.graph
40+ [[1]]
41+ """
42+
843 self .ROW = row
944 self .COL = col
1045 self .graph = graph
1146
47+
48+
1249 def is_safe (self , i : int , j : int , visited : list [list [bool ]]) -> bool :
50+ """
51+ Check if a cell (i, j) is "safe".
52+
53+ We consider a cell "safe" if:
54+ - It is within the bounds of the matrix
55+ - It has not been visited yet
56+ - It contains land (i.e., value is nonzero)
57+
58+ :param i: row index
59+ :param j: column index
60+ :param visitied: 2D list indicating which cells we have visited
61+ :return: True if cell is safe, else False
62+
63+ >>> m = Matrix(3, 3, [[1, 0, 0], [0, 0, 1]])
64+ >>> visited = [[False]*3 for _ in range(3)]
65+
66+ # Within bounds, unvisited, and value is 1 (land)
67+ >>> m.is_safe(0, 0, visited)
68+ True
69+
70+ # Within bounds, unvisited, but value is 0 (water)
71+ >>> m.is_safe(0, 1, visited)
72+ False
73+
74+ # Within bounds, already visited
75+ >>> visited[0][0] = True
76+ >>> m.is_safe(0, 0, visited)
77+ False
78+
79+ # Out of bounds
80+ >>> m.is_safe(3, 0, visited)
81+ False
82+ >>> m.is_safe(-1, 0, visited)
83+ False
84+ """
85+
1386 return (
1487 0 <= i < self .ROW
1588 and 0 <= j < self .COL
@@ -18,20 +91,63 @@ def is_safe(self, i: int, j: int, visited: list[list[bool]]) -> bool:
1891 )
1992
2093 def diffs (self , i : int , j : int , visited : list [list [bool ]]) -> None :
21- # Checking all 8 elements surrounding nth element
22- row_nbr = [- 1 , - 1 , - 1 , 0 , 0 , 1 , 1 , 1 ] # Coordinate order
94+ """
95+ Depth-first search (DFS) to mark all land cells (1s) connected to (i, j) as visited.
96+
97+ :param i: Row index of current cell
98+ :param j: Column index of current cell
99+ :param visited: 2D list tracking visited cells
100+
101+ diffs() checks the 8 cells surrounding the current cell (i, j) and marks the land cells as visited.
102+
103+ >>> graph = [[1, 1, 0], [0, 1, 0], [0, 0, 1]]
104+ >>> m = Matrix(3, 3, graph)
105+ >>> visited = [[False] * 3 for _ in range(3)]
106+ >>> m.diffs(0, 0, visited)
107+ >>> visited[0][0] and visited[0][1] and visited[1][1]
108+ True
109+ >>> visited[2][2]
110+ False
111+ """
112+
113+ # 8 possible movements (N, NE, E, SE, S, SW, W, NW)
114+ row_nbr = [- 1 , - 1 , - 1 , 0 , 0 , 1 , 1 , 1 ]
23115 col_nbr = [- 1 , 0 , 1 , - 1 , 1 , - 1 , 0 , 1 ]
24- visited [i ][j ] = True # Make those cells visited
116+
117+ # Make cells visited
118+ visited [i ][j ] = True
25119 for k in range (8 ):
26- if self .is_safe (i + row_nbr [k ], j + col_nbr [k ], visited ):
27- self .diffs (i + row_nbr [k ], j + col_nbr [k ], visited )
120+ next_i , next_j = i + row_nbr [k ], j + col_nbr [k ]
121+ if self .is_safe (next_i , next_j , visited ):
122+ self .diffs (next_i , next_j , visited )
123+
124+ def count_islands (self ) -> int :
125+ """
126+ Count the number of islands in the matrix.
28127
29- def count_islands (self ) -> int : # And finally, count all islands.
30- visited = [[False for j in range (self .COL )] for i in range (self .ROW )]
128+ :return: Number of islands found
129+
130+ >>> graph[[1, 1, 0], [0, 1, 0], [1, 0, 0]]
131+ >>> m = Matrix(3, 3, graph)
132+ >>> m.count_islands()
133+ 2
134+
135+ >>> graph2 = [[0, 0, 0], [0, 0, 0]]
136+ >>> m2 = Matrix(2, 3, graph2)
137+ >>> m2.count_islands()
138+ 0
139+
140+ >>> graph3 = [[1]]
141+ >>> m3 = Matrix(1, 1, graph3)
142+ >>> m3.count_islands()
143+ 1
144+ """
145+ visited = [[False for _ in range (self .COL )] for _ in range (self .ROW )]
31146 count = 0
32147 for i in range (self .ROW ):
33148 for j in range (self .COL ):
34- if visited [i ][j ] is False and self .graph [i ][j ] == 1 :
149+ if not visited [i ][j ] and self .graph [i ][j ] == 1 :
35150 self .diffs (i , j , visited )
36- count += 1
151+ count += 1
37152 return count
153+
0 commit comments