Traversing a 2D Matrix
The new years first blog is about algorithms – more precisely: 2 dimensional matrices. I want to explore the ways how to find connected 1’s (so called islands) in a 2D array. This problem is also known as the “find the number of islands” or “connected components in an undirected graph“. In this post, we will explore traversing a 2D matrix.
Disclaimer: I generally use my own Algorithms & Data Structures library PHPAlgorithms for examples. If not otherwise declared, the following examples base also on this library.
The subject about this issue is to think in a graph context (even if we talk about 2D arrays). Doing this, we can easily determine that the problem is about a Depth-First-Search (DFS). But lets start with a simple example:
The example shows a 4 x 4 2D matrix with 2 islands denoted by (red) 1’s. The cells with a 0 are non-islands (so called “water”). Before I start, here are some basic definitions:
- Neighbor: any two cells that have both the same value and share a N/S/E/W edge
- Island: The collection of multiple neighbors
The matrix traversing Algorithm
Starting at cell [0/0], the algorithm iterates first over the rows and then the columns. If the current cell is a 1, the algorithm floods through all neighbors (and repeats it for all neighbor’s neighbors) until it reachs the water. At this point, we have to remember that we need a way to remember which cells are already visited in order to prevent multiple visiting (as we are traversing in DFS).
We can use a second “visited” array which contains all visited cells. But personally, I think there’s a much more elegant way: just switching all visited 1’s to 0’s. This makes a second array redundant and the code gets much more elegant. If you consider this approach, do not forget to pass the array by reference as the switching 1’s to 0 will get useless since the most programming language pass variables by value.
This algorithm is repeated for all cells in the array. Whenever a cell with a 1 is found, a counter is incremented (that represents the amount of the islands). The algorithm has a O(n*m) runtime and O(n*m) space complexity.
The matrix traversing Code
Enough theory, let’s start with the code. I am going through each function:
function countIslands(array $matrix) {
$islandCount = 0;
$iSize = count($matrix);
for ($i = 0; $i < $iSize; $i++) {
$jSize = count($matrix[$i]);
for ($j = 0; $j < $jSize; $j++) {
if (isIslandCell($matrix[$i][$j])) {
$islandCount++;
flood($matrix, $i, $j);
}
}
}
return $islandCount;
}What do you think about traversing a 2D matrix? Let me know.
