Cells whose rain reaches both coasts

Graphs Senior Python 3.13+ Reviewed By Best Latest Apps

Pick the fix

Why start the searches from the coast edges instead of from each cell?

Options

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Each coast search visits every cell at most once, so the work is shared

Right: two O(R·C) passes replace one search per cell.

Reversing the flow lets one search answer the question for every cell at once.

Why not the others?
  • B Coast cells are the highest. Heights at the edges can be anything.
  • C Rain cannot flow uphill. That is why the reversed search climbs instead of descends.

30-second answer

Reverse the flow. Start a BFS from every cell on the west edges and climb to neighbours of equal or greater height; that marks every cell that drains west. Do the same from the east edges. The answer is the cells in both sets. O(R·C) time and space.

Practise saying it · 60 s. No recording, just a timer

Explain the reversed multi-source search.

Say your answer out loud, then check which of these points you covered:

  • Start from each coast
  • Climb to equal or higher
  • Intersect the two sets

Deep dive

Searching from each cell downhill is O((R·C)²); reversing the direction shares work between cells.

This is multi-source BFS again, with 'uphill' as the edge rule.

Sorting the output makes the answer deterministic for testing.

Python solution Ran on Python 3.13.5 · mypy --strict
Python 3.13
from collections import deque


STEPS = ((1, 0), (-1, 0), (0, 1), (0, -1))


def both_coasts(height: list[list[int]]) -> list[list[int]]:
    rows, cols = len(height), len(height[0]) if height else 0

    def climb(starts: list[tuple[int, int]]) -> set[tuple[int, int]]:
        seen = set(starts)
        queue = deque(starts)
        while queue:
            r, c = queue.popleft()
            for dr, dc in STEPS:
                y, x = r + dr, c + dc
                inside = 0 <= y < rows and 0 <= x < cols
                if (inside and (y, x) not in seen
                        and height[y][x] >= height[r][c]):
                    seen.add((y, x))
                    queue.append((y, x))
        return seen

    west = climb([(r, 0) for r in range(rows)]
                 + [(0, c) for c in range(cols)])
    east = climb([(r, cols - 1) for r in range(rows)]
                 + [(rows - 1, c) for c in range(cols)])
    return sorted([r, c] for r, c in west & east)

Common mistakes

  • Climbing to strictly higher cells only, which misses flat plateaus.
  • Running the downhill search from every cell and timing out on large maps.

Senior take & follow-ups

Say 'reverse the direction and start from the coasts'. That reframing is the whole insight.

Follow-up questions

Think of your answer first, then open the hint.

  1. What if water can flow diagonally?

    Show hint

    Add the four diagonal neighbours to both searches.

  2. How would you count cells draining to exactly one coast?

    Show hint

    Symmetric difference of the two sets.

From the author

DSA Master - Data & Algorithms

Free on iPhone and iPad: watch 50+ data structures and algorithms step through animations, run the code in the playground, and try the daily challenge.

Suggest a fix if something here is wrong or out of date.