Number of Islands
Count islands in a grid of '1' (land) and '0' (water). Land connects 4-directionally.
Intuition
Every island is one connected component. Scan the grid; each time you step on unvisited land, that is a brand-new island — count it, then flood-fill (sink) the whole component so none of its cells can be counted again. The counter increments exactly once per island because the flood erases the rest of it.
Counting connected components is always the same two-part shape: scan every cell, and whenever you meet an unvisited piece of a component, increment the counter and flood the entire component so it's never counted again. The flood can be DFS or BFS — it makes no difference to the answer. Recognise it whenever the question asks how many groups, as opposed to how large or how far.
Approach
Scan + sink
Loop over every cell. On seeing '1': answer += 1, then DFS from that cell turning every reachable '1' into '0' (or a visited mark).
The flood fill
DFS(r,c): if out of bounds or water, return. Set grid[r][c]='0', recurse into the 4 neighbors. Marking before recursing prevents infinite loops.
Why it counts correctly
The counter only fires on land that survived all previous floods — i.e. land in a component never seen before. One fire per component = number of islands.
Solution & live demo
Common pitfalls
Marking cells visited after recursing instead of on entry
sink(r+1, c); sink(r-1, c); sink(r, c+1); sink(r, c-1) grid[r][c] = "0"
grid[r][c] = "0" sink(r+1, c); sink(r-1, c); sink(r, c+1); sink(r, c-1)
Two adjacent land cells each recurse into the other before either is marked, so the recursion bounces between them until the stack overflows. Mark first, then explore — the mark is what terminates the search.
Checking bounds at the call site
if r + 1 < R and grid[r+1][c] == "1": sink(r+1, c) if r - 1 >= 0 and grid[r-1][c] == "1": sink(r-1, c)
def sink(r, c):
if r < 0 or r >= R or c < 0 or c >= C or grid[r][c] != "1":
returnThe same four conditions get written at every call site, and one typo among them is easy to miss. Validating once at the top of the function covers all four directions and both recursion and the initial call.
Comparing against integers when the grid holds strings
if grid[r][c] != 1:
if grid[r][c] != "1":
LeetCode passes this grid as characters, not numbers. "1" != 1 is always true in Python, so every cell reads as water and the count comes back 0.
Edge cases
Counter never fires — 0.
First cell fires, flood sinks everything — 1.
Diagonals are not connections; such islands count separately.