By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(Complete Guide for FAANG-Level Interviews)
"This problem tests your ability to model multi-directional constraints—master it, and you’ll crush 1 in 4 graph-based interview questions at FAANG, especially at Google and Meta."
pacific_reachable[i][j] = True
(i,j)
pacific_reachable[i][j] and atlantic_reachable[i][j]
(i±1, j)
(i, j±1)
(Repeatable mental checklist for every "Pacific Atlantic" problem)
Goal: Find all cells that can flow to both oceans.
Model the Grid
heights[m][n]
Define 4-directional movement: (i±1, j) and (i, j±1).
Reverse the Problem
This avoids simulating all possible paths from every cell.
Initialize BFS/DFS from Ocean Boundaries
Use a queue for BFS or a stack for DFS.
Track Reachable Cells
m x n
pacific_reachable[i][j]
True
atlantic_reachable[i][j]
Initialize both with False.
False
Propagate Reachability
(ni, nj)
heights[ni][nj] >= heights[i][j]
Optimization: Skip cells already marked by both oceans.
Collect Results
Iterate through all cells. If pacific_reachable[i][j] and atlantic_reachable[i][j], add (i,j) to the result.
Edge Cases
[]
Problem:
[ [1, 2, 2, 3], [3, 2, 3, 4], [2, 4, 5, 3], [6, 7, 1, 4] ]
Solution: 1. Pacific BFS: Start from (0,0), (0,1), (0,2), (0,3), (1,0), (2,0), (3,0). - Propagate to cells where heights[ni][nj] >= heights[i][j]. - Mark reachable cells in pacific_reachable. 2. Atlantic BFS: Start from (3,0), (3,1), (3,2), (3,3), (0,3), (1,3), (2,3). - Propagate similarly. 3. Result: Cells where both matrices are True: - (0,3), (1,3), (2,2), (3,0), (3,1).
(0,0)
(0,1)
(0,2)
(0,3)
(1,0)
(2,0)
(3,0)
pacific_reachable
(3,1)
(3,2)
(3,3)
(1,3)
(2,3)
(2,2)
Python Code:
from collections import deque def pacificAtlantic(heights): if not heights or not heights[0]: return [] m, n = len(heights), len(heights[0]) pacific_reachable = [[False] n for _ in range(m)] atlantic_reachable = [[False] n for _ in range(m)] def bfs(queue, reachable): directions = [(1,0), (-1,0), (0,1), (0,-1)] while queue: i, j = queue.popleft() for di, dj in directions: ni, nj = i + di, j + dj if 0 <= ni < m and 0 <= nj < n and not reachable[ni][nj] and heights[ni][nj] >= heights[i][j]: reachable[ni][nj] = True queue.append((ni, nj)) # Pacific BFS (top and left edges) pacific_queue = deque() for i in range(m): pacific_queue.append((i, 0)) pacific_reachable[i][0] = True for j in range(n): pacific_queue.append((0, j)) pacific_reachable[0][j] = True bfs(pacific_queue, pacific_reachable) # Atlantic BFS (bottom and right edges) atlantic_queue = deque() for i in range(m): atlantic_queue.append((i, n-1)) atlantic_reachable[i][n-1] = True for j in range(n): atlantic_queue.append((m-1, j)) atlantic_reachable[m-1][j] = True bfs(atlantic_queue, atlantic_reachable) # Collect results result = [] for i in range(m): for j in range(n): if pacific_reachable[i][j] and atlantic_reachable[i][j]: result.append([i, j]) return result
Time Complexity: O(m n) (each cell is visited at most twice). Space Complexity: O(m n) (for the two reachability matrices).
O(m n)
Why This Works: - Reverse BFS ensures we only traverse cells that can flow to the ocean, avoiding exponential path checks. - Multi-source BFS efficiently propagates reachability from all boundary cells simultaneously.
[ [1, 1, 1], [1, 1, 1], [1, 1, 1] ]
Solution: - All cells are on the boundary or can flow to both oceans (since all heights are equal). - Result: All 9 cells.
Python Code: (Same as above, but the BFS will mark all cells as reachable.)
Why This Works: - Equal heights allow water to flow in any direction, so all boundary cells propagate reachability to the entire grid.
Problem: "Can you solve this with O(1) extra space (excluding the result)?" Solution: - Use bitmasking to store reachability in a single integer per cell (e.g., reachable[i][j] = 1 for Pacific, 2 for Atlantic, 3 for both). - Alternatively, modify the input grid in-place (if allowed).
reachable[i][j] = 1
2
3
Optimized Python Code:
def pacificAtlantic_optimized(heights): if not heights or not heights[0]: return [] m, n = len(heights), len(heights[0]) reachable = [[0] n for _ in range(m)] # 0: unreachable, 1: Pacific, 2: Atlantic, 3: both def dfs(i, j, ocean): reachable[i][j] |= ocean for di, dj in [(1,0), (-1,0), (0,1), (0,-1)]: ni, nj = i + di, j + dj if 0 <= ni < m and 0 <= nj < n and (reachable[ni][nj] & ocean) == 0 and heights[ni][nj] >= heights[i][j]: dfs(ni, nj, ocean) # Pacific DFS (top and left edges) for i in range(m): dfs(i, 0, 1) for j in range(n): dfs(0, j, 1) # Atlantic DFS (bottom and right edges) for i in range(m): dfs(i, n-1, 2) for j in range(n): dfs(m-1, j, 2) # Collect results result = [] for i in range(m): for j in range(n): if reachable[i][j] == 3: result.append([i, j]) return result
Time Complexity: O(m n) (same as BFS). Space Complexity: O(m n) (but uses a single matrix instead of two).
Why This Works: - Bitmasking reduces space by combining two boolean matrices into one integer matrix. - DFS is used here for simplicity, but BFS would work similarly.
(i+1, j+1)
O(mn)
"Here’s your 60-second cheat sheet for Pacific Atlantic Water Flow: 1. Reverse the problem: Instead of checking if water flows from a cell to the ocean, check if the ocean can reach the cell via an ascending path. 2. Multi-source BFS/DFS: Start from all Pacific (top/left) and Atlantic (bottom/right) boundary cells. 3. Track reachability: Use two matrices (or bitmasking) to mark cells that can flow to each ocean. 4. Collect results: Cells marked in both matrices are your answer. 5. Edge cases: Handle empty grids, single-row/column grids, and equal heights. This approach is optimal—O(mn) time and space—and demonstrates your ability to model constraints efficiently. Now go crush that interview!
This framework is directly usable in an interview—no fluff, just actionable steps. Good luck! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.