Read-only web browser

Solutions

Browse the interview solutions folder with syntax highlighting.

pacific-atlantic-water-flow.py

graphs/pacific-atlantic-water-flow.py · Python · 3.2 KiB · 2026-03-26 21:07

Back to folder
# Start from the boarders and explore (DFS inwards) to find all cells that can reach the Atlantic. Do the same with the Pacific. Then find the intersection of the two sets of cells.
# graphs

# DFS - O(M*N) time, O(M*N) space
def pacificAtlantic(heights: list[list[int]]) -> list[list[int]]:
    ROWS, COLS = len(heights), len(heights[0])
    pacific = set()
    atlantic = set()

    def dfs(r: int, c: int, prev: int, visited: set):
        if r<0 or r>=ROWS or c<0 or c>=COLS or \
            heights[r][c] < prev or (r,c) in visited:
            return

        val = heights[r][c]
        visited.add((r,c))
        dfs(r+1, c, val, visited)
        dfs(r-1, c, val, visited)
        dfs(r, c+1, val, visited)
        dfs(r, c-1, val, visited)
    
    # Add borders as part of the DFS (as first cells visited)
    for c in range(COLS):
        dfs(0, c, heights[0][c], pacific)
        dfs(ROWS-1, c, heights[ROWS-1][c], atlantic)

    for r in range(ROWS):
        dfs(r, 0, heights[r][0], pacific)
        dfs(r, COLS-1, heights[r][COLS-1], atlantic)

    return list(pacific & atlantic)


# BFS - O(M*N) time, O(M*N) space
def pacificAtlantic(heights: list[list[int]]) -> list[list[int]]:
    ROWS, COLS = len(heights), len(heights[0])
    directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
    pac = [[False] * COLS for _ in range(ROWS)]
    atl = [[False] * COLS for _ in range(ROWS)]

    from collections import deque

    def bfs(source, ocean):
        q = deque(source)
        while q:
            r, c = q.popleft()
            ocean[r][c] = True
            for dr, dc in directions:
                nr, nc = r + dr, c + dc
                if (0 <= nr < ROWS and 0 <= nc < COLS and
                    not ocean[nr][nc] and
                    heights[nr][nc] >= heights[r][c]
                ):
                    q.append((nr, nc))

    pacific = []
    atlantic = []
    for c in range(COLS):
        pacific.append((0, c))
        atlantic.append((ROWS - 1, c))

    for r in range(ROWS):
        pacific.append((r, 0))
        atlantic.append((r, COLS - 1))

    bfs(pacific, pac)
    bfs(atlantic, atl)

    res = []
    for r in range(ROWS):
        for c in range(COLS):
            if pac[r][c] and atl[r][c]:
                res.append([r, c])
    return res


# Brute force - O(M*N*4^(M*N)) time, O(M*N) space
def pacificAtlantic(heights: list[list[int]]) -> list[list[int]]:
    ROWS, COLS = len(heights), len(heights[0])
    directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]

    pacific = atlantic = False

    def dfs(r, c, prevVal):
        nonlocal pacific, atlantic
        if r < 0 or c < 0:
            pacific = True
            return
        if r >= ROWS or c >= COLS:
            atlantic = True
            return
        if heights[r][c] > prevVal:
            return

        tmp = heights[r][c]
        heights[r][c] = float('inf')
        for dx, dy in directions:
            dfs(r + dx, c + dy, tmp)
            if pacific and atlantic:
                break
        heights[r][c] = tmp

    res = []
    for r in range(ROWS):
        for c in range(COLS):
            pacific = False
            atlantic = False
            dfs(r, c, float('inf'))
            if pacific and atlantic:
                res.append([r, c])
    return res