◀ THE GRIND — GRAPHS

Surrounded Regions

MEDIUM✓ CHIP-TIMEDLC #130 — FULL STATEMENT ↗

The drill: In a grid of 'X' and 'O', flip every 'O' to 'X' unless it belongs to a group of connected O's that touches the border — those escape untouched, everything fully enclosed gets captured.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A board of 'X' and 'O' characters holds regions of connected O's. Any region of O's that touches the border of the board — directly or through a chain of other O's — is safe; every other region is fully enclosed and gets flipped to X.

The flip happens in place, on the same board that was passed in — there's no separate structure to build up and return, just the board with every captured region converted.

A single O sitting on the border counts as touching it, and that safety spreads to every O connected to it, no matter how deep into the board that connected group reaches.

EX 01
board = ["XX", "XX"]
["XX", "XX"]
NO O'S AT ALL
EX 02
board = ["XXX", "XOX", "XXX"]
["XXX", "XXX", "XXX"]
SINGLE FULLY ENCLOSED O
EX 03
board = ["OXX", "XXX", "XXX"]
["OXX", "XXX", "XXX"]
O SITS DIRECTLY ON THE BORDER
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

A region of O's survives only if some path of O's inside it reaches the edge of the board — otherwise every O in it gets flipped. Checking each region in isolation for 'does it touch a wall' works, but it repeats a lot of exploring.

HINT 2 THE STRUCTURE

Flip the question: instead of asking which regions are enclosed, mark which O's are safe by flood-filling inward from the border first — everything the border-flood never reaches was enclosed all along.

HINT 3 ONE STEP FROM THE ANSWER

Flood-fill from every border 'O' first, marking each one reached with a temporary marker, then make one final pass over the whole board: any remaining 'O' becomes 'X', and every marked cell reverts back to 'O'.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE BORDER-FIRST FLOODPATTERN · FLOOD FROM THE BORDER FIRSTboard 4×5 · one region captured, one escapes
X
X
X
X
X
X
O
O
X
X
X
X
X
X
O
X
X
X
X
X
STEP 1

Scan every border cell first — any O touching the edge, directly or through a chain, survives. Everything else gets captured.

STEP 1 / 6 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/surrounded-regions.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def solve(self, board: List[List[str]]) -> None:
        rows, cols = len(board), len(board[0])

        def flood(r, c):
            stack = [(r, c)]
            board[r][c] = 'S'
            while stack:
                cr, cc = stack.pop()
                for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    nr, nc = cr + dr, cc + dc
                    if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc] == 'O':
                        board[nr][nc] = 'S'
                        stack.append((nr, nc))

        for r in range(rows):
            for c in (0, cols - 1):
                if board[r][c] == 'O':
                    flood(r, c)
        for c in range(cols):
            for r in (0, rows - 1):
                if board[r][c] == 'O':
                    flood(r, c)

        for r in range(rows):
            for c in range(cols):
                if board[r][c] == 'O':
                    board[r][c] = 'X'
                elif board[r][c] == 'S':
                    board[r][c] = 'O'
TIME O(ROWS·COLS)SPACE O(ROWS·COLS)PYTHON · RACE PACE · 30 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED