This approach involves performing a DFS from the cells adjacent to the Pacific and Atlantic oceans separately to determine reachable cells for each ocean and then finding their intersection.
The Pacific Ocean can be reached from any cell on the top row or leftmost column. Similarly, the Atlantic Ocean can be reached from any cell on the bottom row or rightmost column. We perform DFS from these boundary cells to mark all cells that can flow into the corresponding ocean. Finally, the intersection of these two sets gives cells that can reach both oceans.
Time Complexity: O(m * n), where m is the number of rows and n is the number of columns. Each cell is processed once for each ocean.
Space Complexity: O(m * n), as sets used to keep track of visited cells for both oceans.
1def pacificAtlantic(heights):
2 if not heights or not heights[0]:
3 return []
4
5 def dfs(x, y, reach):
6 reach.add((x, y))
7 for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]: # directions
8 nx, ny = x + dx, y + dy
9 if 0 <= nx < m and 0 <= ny < n and (nx, ny) not in reach and heights[nx][ny] >= heights[x][y]:
10 dfs(nx, ny, reach)
11
12 m, n = len(heights), len(heights[0])
13 pacific_reach, atlantic_reach = set(), set()
14
15 for i in range(m):
16 dfs(i, 0, pacific_reach) # Pacific Ocean
17 dfs(i, n-1, atlantic_reach) # Atlantic Ocean
18
19 for j in range(n):
20 dfs(0, j, pacific_reach) # Pacific Ocean
21 dfs(m-1, j, atlantic_reach) # Atlantic Ocean
22
23 return list(pacific_reach & atlantic_reach)
The above function defines a DFS method and applies it from each pacific and atlantic border cell. For pacific, it applies DFS from top row and left column, while for atlantic, it's from bottom row and right column.
DFS explores in four directions, making recursive calls when conditions are satisfied, and keeps track of reachable cells using sets.
Instead of DFS, we can use BFS to achieve a similar result. This involves starting from the ocean-bordering cells and performing a level-order traversal to mark reachable cells, iteratively checking neighbors in a queue-based manner. BFS might be preferred in scenarios where recursion depth in DFS isn't ideal or could lead to stack overflow.
The idea is to initiate BFS from each ocean's boundary simultaneously, progressively marking each reachable cell, and determining intersecting positions for final results.
Time Complexity: O(m * n), where BFS is performed from a subset of cells and checks neighbors iteratively.
Space Complexity: O(m * n), contingent upon queue operations and reachability matrices.
1from collections import deque
2
3def pacificAtlantic(heights):
4 if not heights or not heights[0]:
5 return []
6
7 m, n = len(heights), len(heights[0])
8 pacific = [[False] * n for _ in range(m)]
9 atlantic = [[False] * n for _ in range(m)]
10
11 def bfs(starts, ocean):
12 queue = deque(starts)
13 while queue:
14 x, y = queue.popleft()
15 ocean[x][y] = True
16 for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
17 nx, ny = x + dx, y + dy
18 if 0 <= nx < m and 0 <= ny < n:
19 if not ocean[nx][ny] and heights[nx][ny] >= heights[x][y]:
20 queue.append((nx, ny))
21 ocean[nx][ny] = True
22
23 pacific_starts = [(i, 0) for i in range(m)] + [(0, j) for j in range(n)]
24 atlantic_starts = [(i, n-1) for i in range(m)] + [(m-1, j) for j in range(n)]
25
26 bfs(pacific_starts, pacific)
27 bfs(atlantic_starts, atlantic)
28
29 return [[x, y] for x in range(m) for y in range(n) if pacific[x][y] and atlantic[x][y]]
This function uses a deque to implement BFS from both Pacific and Atlantic borders. Starting points are defined for each ocean, and a queue processes each cell, enqueuing adjacent cells that retain valid flow conditions.
The results are gathered similarly by intersecting valid Pacific and Atlantic reachable positions.