The Problem
Given an m x n 2D binary grid grid, which represents a map of '1's (land) and '0's (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are surrounded by water.
Examples
Input: grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
Output: 1
Input: grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
Output: 3
Constraints
m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]is'0'or'1'.
Depth-First Search Solution
func numIslands(_ grid: [[Character]]) -> Int {
var grid = grid
let ROWS = grid.count
let COLS = grid[0].count
let directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
var islands = 0
func dfs(_ r: Int, _ c: Int) {
if (r < 0 || c < 0 || r >= ROWS ||
c >= COLS || grid[r][c] == "0"
) {
return
}
grid[r][c] = "0"
for direction in directions {
let dr = direction[0]
let dc = direction[1]
dfs(r + dr, c + dc)
}
}
for r in 0 ..< ROWS {
for c in 0 ..< COLS {
if grid[r][c] == "1" {
dfs(r, c)
islands += 1
}
}
}
return islands
}
Explanation
From the description of the problem, we can see that we have islands formed by connecting adjacent land horizontally or vertically. If we draw a visual representation, we can find islands that are connected vertically or horizontally and surrounded by water.
When the problem has adjacent elements, this means that it is a graph problem, and we have two common ways to solve it: using DFS or BFS algorithms.
To do that, we need to visit neighboring cells and check if they are part of the island (have "1").
The function dfs will help us check for an out-of-bounds case and if we have already visited this cell. After that, we will mark the current cell as "0", meaning that we have visited this cell, and recursively call dfs to search neighbors in four directions.
Time/Space Complexity
- Time complexity: O(m*n)
- Space complexity: O(m*n)
- Where
mis the number of rows andnis the number of columns in thegrid.
Breadth-First Search Solution
func numIslands(_ grid: [[Character]]) -> Int {
let ROWS = grid.count
let COLS = grid[0].count
var visit: Set<[Int]> = []
var islands = 0
func bfs(_ r: Int, _ c: Int) {
var q: [[Int]] = []
visit.insert([r, c])
q.append([r, c])
while !q.isEmpty {
let val = q.removeFirst()
let row = val[0]
let col = val[1]
let directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
for direction in directions {
let r = row + direction[0]
let c = col + direction[1]
if ((0 ..< ROWS).contains(r) &&
(0 ..< COLS).contains(c) &&
grid[r][c] == "1" &&
!visit.contains([r, c])
) {
q.append([r, c])
visit.insert([r, c])
}
}
}
}
for r in 0 ..< ROWS {
for c in 0 ..< COLS {
if grid[r][c] == "1" && !visit.contains([r, c]) {
bfs(r, c)
islands += 1
}
}
}
return islands
}
Explanation
We can solve this problem using the BFS algorithm. The idea behind it is that we add an additional visit set and move layer by layer, starting from position (0,0).
The BFS algorithm is slightly different from DFS because it is iterative and uses a queue data structure. However, the logic remains the same: we visit neighboring cells in four directions only if
- we are not out of bounds
- the cell is equal to
"1" - and we have not visited the cell before.
Time/Space Complexity
- Time complexity: O(m*n)
- Space complexity: O(m*n)
- Where
mis the number of rows andnis the number of columns in thegrid.