Number of Islands

Each unvisited land cell launches a flood fill that sinks its whole island.

Scan and Flood Fill

islands = 0, and no cell has been seen. The scan reads the 4 × 4 grid row by row.
StopGridExport
grid
1100100100110000
queueempty
islands0
  • CH4 queue

Problem

You are given a rectangular grid containing land cells marked 1 and water cells marked 0. Count the number of islands, where an island is a group of horizontally or vertically adjacent land cells; diagonal contact does not connect cells. Return the total number of distinct islands.

Examples

Input: grid = [["1","1","0","0"],["1","0","0","1"],["0","0","1","1"],["0","0","0","0"]]

Output: 2

The upper-left cells form one island. The land at the right and lower middle connects into a second island.

Input: grid = [["1","0","1"],["0","1","0"],["1","0","1"]]

Output: 5

No two land cells share an edge, so every land cell is its own island.

The Goal

Count the islands in a grid of "1" (land) and "0" (water). An island is land cells joined up, down, left or right. Cells that only touch at a corner don't connect.

Scan the grid in reading order. The first land cell of an island that the scan meets starts a flood fill, which reaches every cell of that island. So each island is counted once, when the scan finds its first cell.

One flood fill, one island

Land the scan reaches before any flood fill has starts a new island. Every other land cell belongs to an island already counted.

Count flood fills, not land cells.

Key Idea: Mark a Cell When You Queue It

A flood fill keeps a queue of cells to visit and a seen set. Mark a cell seen the moment you queue it, not when you pop it. Then no cell is queued twice, even when two of its neighbors both reach it.

Later, when the scan passes a cell that's already seen, it skips it. That island is already counted.

A cell is marked seen as it's queued.

No cell is queued twice.

The Algorithm

The outer loops find islands. The while loop drains one island's queue.

python
from collections import deque

def num_islands(grid):
    rows, cols = len(grid), len(grid[0])
    seen = set()
    islands = 0
    for r in range(rows):
        for c in range(cols):
            if grid[r][c] != "1" or (r, c) in seen:
                continue
            islands += 1
            seen.add((r, c))
            queue = deque([(r, c)])
            while queue:
                row, col = queue.popleft()
                for nr, nc in ((row + 1, col), (row - 1, col), (row, col + 1), (row, col - 1)):
                    if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == "1" and (nr, nc) not in seen:
                        seen.add((nr, nc))
                        queue.append((nr, nc))
    return islands

A depth-first fill swaps the queue for a stack or recursion and counts the same islands.

ApproachHow it finds an islandExtra space
BFSDrains a queue from the first cellO(R · C)
DFSRecursion or a stack from the first cellO(R · C), as deep as the island
Union-FindMerges neighboring land, then counts groupsO(R · C)

Walkthrough

Run it on the 4 × 4 grid. The scan meets (0,0) first: islands = 1. Its fill queues (1,0) and (0,1), and neither has new land beside it, so island 1 is three cells.

The scan skips (0,1) and (1,0), already seen. At (1,3) it finds fresh land: islands = 2. That fill reaches (2,3), then (2,2). Every other cell is water or already seen, so the answer is 2.

Checkpoint · predict the next step

Step 11 of 34 on the stage: Scan (0,1): land, but island 1's flood fill already reached it. Skip it.

scan at (0, 1) · queue = [] · islands 1

What does step 12 show?
Step through it on the stage

Pitfalls

  • Mark cells when you queue them. Marking on pop lets a cell be queued twice when two neighbors reach it.
  • Check the bounds before you read grid[nr][nc].
  • Diagonal land doesn't connect: ["101","010","101"] is 5 islands.
  • All water is 0 islands, and all land is 1.
  • Recursive DFS on a long, thin island can pass Python's recursion limit. The queue can't.

When should a cell be marked seen?

Another Way: Union-Find

Union-Find reaches the same count without a flood fill. Start with every land cell in a group of its own. For each pair of neighboring land cells, merge their groups. The answer is the number of groups left.

The example has six land cells and four neighboring pairs, and every merge joins two groups, so 2 are left.

What does one flood fill count?

1 / 2

Complexity

Say the grid has R rows and C columns. The scan reads each cell once. Each land cell is queued once and checks four neighbors, so the fills add O(R · C) more. Time is O(R · C).

The seen set and the queue can each hold every cell of an all-land grid, so space is O(R · C) too.

Scan plus flood fill

Time
O(n)
Space
O(n)
Where the time goes
  • Scan every cellHere n = R · C.dominantO(n)
  • Fill each islandEach land cell is queued once and checks 4 neighbors.dominantO(n)
  • Seen set and queueAn all-land grid fills both.dominantO(n)
How it grows
input size n →opsO(n²)O(n log n)O(n)O(log n)O(1)
Roughly what that costs
n101001,00010,000
O(n)101001K10K

Linear in the grid: every cell has to be read once anyway.

In short

Scan the grid; when you hit unvisited land, increment the count and DFS/BFS to mark every connected land cell visited (flood fill). Union-Find is an alternative that merges adjacent land cells and counts components.

TimeO(rows·cols)SpaceO(rows·cols) worst case

Common mistake

Not marking cells visited (or not marking them immediately), causing recounting or infinite recursion.