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.length
n == grid[i].length
1 <= m, n <= 300
grid[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
m
is the number of rows andn
is 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
m
is the number of rows andn
is the number of columns in thegrid
.