This is the dynamic version of the classic "Number of Islands" problem. In the original problem (LeetCode #200), you get a fixed grid and count connected components of land cells. Here, the grid starts empty and land cells are added one at a time. After each addition, we report the current island count.
The challenge is doing this efficiently. Each time we add a land cell, only its four neighbors can change connectivity, so rerunning a full BFS or DFS over the whole grid after every addition wastes work. When the new cell touches an existing island, it joins that island. When it touches two or more separate islands at once, those islands merge into one and the total count drops. We need a structure that handles these incremental merges without rescanning everything.
Union Find (Disjoint Set Union) matches this shape directly. It groups elements dynamically and answers whether two elements are in the same group, which is what tracking islands as land arrives requires.
1 <= m, n <= 10^4 -> The grid can be up to 10^4 x 10^4 = 10^8 cells, too large to allocate as a full m x n array. We work only with the cells that become land, of which there are at most 10^4.1 <= positions.length <= 10^4 -> At most 10,000 addLand operations. To keep the total cost manageable, each operation needs to be close to O(1).0 <= r_i < m, 0 <= c_i < n -> Positions are always within bounds, but duplicates are allowed: a position may repeat, meaning we add land to a cell that is already land. The count must not change on a duplicate.Treat each operation as a fresh "Number of Islands" problem. Maintain a grid, and after each addLand, run a full BFS over the entire grid to count connected components from scratch.
For each addLand, mark the cell as land, then iterate over the grid. Every time you find an unvisited land cell, start a BFS to mark all connected land cells as visited, and increment the island count.
m x n grid initialized to all water (0).positions:grid[r][c] = 1 (land).Loading animation...
With k up to 10^4 and the grid up to 10^8 cells, O(k m n) is far too slow, and allocating the full grid is not even possible at the upper bound. The next approach keeps the connectivity information between operations instead of rebuilding it, updating only what the new cell affects.
Maintain a running island count and update it as each cell arrives. When we add a new land cell, it starts as its own island, so the count goes up by 1. Then we check the four neighbors. For each neighbor that is already land and sits in a different island, we union the two and decrement the count by 1. After processing all four neighbors, the count is the answer for this operation.
Union Find supports two operations: find(x) returns the representative of x's group, and union(x, y) merges two groups. With path compression in find and union by rank, both run in nearly O(1) amortized time, measured as O(alpha(mn)) where alpha is the inverse Ackermann function.
The grid can hold up to 10^8 cells but at most 10^4 become land, so we store the parent and rank in a HashMap keyed only by land cells instead of allocating a full array. Each 2D coordinate maps to a single integer key with row * n + col, which is unique because every column index is less than n.
The count update is correct even when the new cell touches several existing islands at once. Adding the cell first raises the count by 1. Then each neighbor is examined in turn: the first union check that succeeds folds the new cell into one island, and every later neighbor that still has a different root represents a genuinely separate island being joined for the first time. Each such union decrements the count by exactly 1, so joining a cell that bridges three previously separate islands runs count++ once and count-- three times, a net drop of 2. The same-root check prevents double counting when two neighbors already belong to the same island.
parent, an empty HashMap rank, and count = 0.(r, c) in positions:id = r * n + c.id is already in parent (duplicate addLand), append the current count and skip.id to parent with parent[id] = id (self-root), set rank[id] = 0, and increment count.(nr, nc). For each neighbor that is already land (exists in parent):count.count to the result.Loading animation...