Pacific Atlantic Water Flow. — Cracked Java
// Data Structures & Algorithms · Graphs — Representation, BFS, DFS
SeniorCoding

Pacific Atlantic Water Flow.

Problem. Given an m × n grid of cell heights, water flows from a cell to a neighbor (4-directional) of equal or lower height. The Pacific touches the top and left edges; the Atlantic touches the bottom and right edges. Return all cells from which water can reach both oceans.

The key insight — reverse the flow

The brute force runs a search from every cell asking "can this reach each ocean?" — O((m·n)²), far too slow. Flip the direction: instead of asking where water flows to, start from each ocean's border and search inward to every cell water could have flowed from — i.e., move to a neighbor of equal or greater height. A cell reachable in both reverse searches can drain to both oceans.

Two multi-source traversals, one per ocean, each O(m·n). Intersect the two reachable sets.

Approach — DFS from both borders, O(m·n) time, O(m·n) space

public List<List<Integer>> pacificAtlantic(int[][] h) {
    int m = h.length, n = h[0].length;
    boolean[][] pac = new boolean[m][n], atl = new boolean[m][n];

    for (int r = 0; r < m; r++) {          // left col -> Pacific, right col -> Atlantic
        dfs(h, pac, r, 0);
        dfs(h, atl, r, n - 1);
    }
    for (int c = 0; c < n; c++) {          // top row -> Pacific, bottom row -> Atlantic
        dfs(h, pac, 0, c);
        dfs(h, atl, m - 1, c);
    }

    List<List<Integer>> res = new ArrayList<>();
    for (int r = 0; r < m; r++)
        for (int c = 0; c < n; c++)
            if (pac[r][c] && atl[r][c]) res.add(List.of(r, c));
    return res;
}

private void dfs(int[][] h, boolean[][] reach, int r, int c) {
    reach[r][c] = true;
    int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
    for (int[] d : dirs) {
        int nr = r + d[0], nc = c + d[1];
        if (nr < 0 || nc < 0 || nr >= h.length || nc >= h[0].length) continue;
        if (reach[nr][nc]) continue;               // already visited
        if (h[nr][nc] < h[r][c]) continue;         // reverse flow: must be >= current
        dfs(h, reach, nr, nc);
    }
}

Each ocean's DFS visits each cell at most once, so the total is O(m·n) time and O(m·n) space for the two visited matrices plus the recursion stack.

Mark your status