HardArrayHash TableUnion FindUpdated Sep 2026

305. Number of Islands II

Asked at Uber

Difficulty

Hard

Time

O(k * α(m*n))

Space

O(m*n)

Pattern

Array

Companies

1

Problem

You start with an m x n grid that is all water. You are given a list of positions. Each position [r, c] is an operation that turns that water cell into land.

After each operation, you must report how many islands exist. An island is a group of land cells connected horizontally or vertically (not diagonally). Water separates islands.

Return an array answer where answer[i] is the number of islands right after the i-th operation. If a position is already land, the grid does not change, but you still record the current island count.

Adding land one cell at a time

grid012012110001010Green cells form one island, orange is a second, blueis a third — answer [1,1,2,3].
Each operation flips one water cell to land, and we count the separate land groups after every flip.

Constraints

  • ●1 <= m, n, positions.length <= 10^4
  • ●1 <= m * n <= 10^4
  • ●positions[i].length == 2
  • ●0 <= ri < m
  • ●0 <= ci < n

Examples

Example 1
Inputm = 3, n = 3, positions = [[0,0],[0,1],[1,2],[2,1]]
Output[1,1,2,3]
WhyAfter (0,0) there is one island. Adding (0,1) touches it, so still one island. Adding (1,2) is far away, so now two islands. Adding (2,1) touches (1,2) but not the first island, so the count becomes three.
Example 2
Inputm = 1, n = 1, positions = [[0,0]]
Output[1]
WhyThe only cell becomes land, so there is exactly one island.

Asked At

1 companies
CompanyDifficulty
UberHardView all Uber questions →

How to Think About It

1

Brute force: after each addition, run BFS/DFS on the entire grid to count islands — O(m * n * k) time.

2

Use Union-Find to maintain connected components as cells are added incrementally.

3

When adding a cell, initialize it as its own component and union it with any adjacent land cells.

4

Track the number of components: start at 0, add 1 for each new cell, subtract 1 for each successful union.

5

Optimal: Union-Find with path compression and union by rank gives near O(1) per operation amortized.

Optimal Approach

Use a Union-Find data structure. For each added land cell, create a new component and check its four neighbors. If a neighbor is land, union the two cells and decrement the component count. After processing each addition, record the current number of distinct islands. Union-Find with path compression and union by rank ensures each operation is amortized O(α(mn)) ≈ O(1), giving overall O(k * α(mn)) time.

Union-Find tracks island count

after (0,0)012012100000000New cell becomes its own component: count = 0 + 1 = 1.after (0,1)012012110000000(0,1) touches land at (0,0), so union them: count = 2− 1 = 1.after (1,2)012012110001000(1,2) has no land neighbors, so count = 1 + 1 = 2.count += 1 for each new landcount -= 1 for each successful unionanswer.append(count)
Start count at 0. Each new land adds 1; each successful union with a land neighbor subtracts 1.
ComplexityTime O(k * α(m*n))Space O(m*n)k is the number of positions; each add does a constant number of Union-Find operations, which are near O(1) amortized thanks to path compression and union by rank.

What Trips People Up in Real Interviews

1

Clarify whether the grid dimensions are fixed or dynamic — they are fixed here.

2

Map 2D coordinates to 1D IDs using id = row * nCols + col for the Union-Find array.

3

Remember that adding a water cell (already land) does not change the island count.

4

Ask if diagonal adjacency counts — it does not, only horizontal and vertical.

5

Explain path compression and union by rank to justify the amortized time complexity.

Solution Code

O(k * α(m*n)) time
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
        self.count = 0

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py:
            return False
        if self.rank[px] < self.rank[py]:
            px, py = py, px
        self.parent[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1
        self.count -= 1
        return True

    def numIslands2(self, m, n, positions):
        uf = UnionFind(m * n)
        grid = [[0] * n for _ in range(m)]
        result = []
        dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        for r, c in positions:
            if grid[r][c] == 1:
                result.append(uf.count)
                continue
            grid[r][c] = 1
            uf.count += 1
            idx = r * n + c
            for dr, dc in dirs:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n and grid[nr][nc] == 1:
                    uf.union(idx, nr * n + nc)
            result.append(uf.count)
        return result

Pro at DSA?

Test your skills with a real FAANG-style mock interview.

Start a Mock Interview →

Frequently Asked Questions

What is the Number of Islands II problem?

You are given an empty 2D grid and a list of positions to be added one at a time. Each position turns a water cell into a land cell. After each addition, return the number of distinct islands in the grid. Two cells are part of the same island if they are adjacent horizontally or vertically.

How do you solve Number of Islands II?

The optimal approach runs in O(k * α(m*n)) time and O(m*n) space. Scroll up to "Optimal Approach" for the step-by-step walkthrough, diagrams, and code in Python, C++ and Java.

What companies ask Number of Islands II?

Number of Islands II is asked at Uber. It is a hard difficulty problem.

What are common mistakes on Number of Islands II?
  • Clarify whether the grid dimensions are fixed or dynamic — they are fixed here.
  • Map 2D coordinates to 1D IDs using id = row * nCols + col for the Union-Find array.
  • Remember that adding a water cell (already land) does not change the island count.
  • Ask if diagonal adjacency counts — it does not, only horizontal and vertical.
  • Explain path compression and union by rank to justify the amortized time complexity.