There is an m x n
rectangular island that borders both the Pacific Ocean and Atlantic Ocean. The Pacific Ocean touches the island's left and top edges, and the Atlantic Ocean touches the island's right and bottom edges.
The island is partitioned into a grid of square cells. You are given an m x n
integer matrix heights
where heights[r][c]
represents the height above sea level of the cell at coordinate (r, c)
.
The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell's height is less than or equal to the current cell's height. Water can flow from any cell adjacent to an ocean into the ocean.
Return a 2D list of grid coordinates result
* where* result[i] = [r_i, c_i]
* denotes that rain water can flow from cell* (r_i, c_i)
* to both the Pacific and Atlantic oceans*.
For example: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]] Output: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
heights = [[1]] Output: [[0,0]]
Constraints: m == heights.length n == heights[r].length 1 <= m, n <= 200 0 <= heights[r][c] <= 10^5
## Data Structures & Algorithms: Pacific Atlantic Water Flow
This problem asks us to find all the cells in a matrix from which water can flow to both the Pacific and Atlantic oceans. The water can only flow to neighboring cells with heights less than or equal to the current cell. The Pacific Ocean borders the top and left edges, and the Atlantic Ocean borders the bottom and right edges.
### 1. Naive Solution (Brute Force)
The brute force approach would involve starting at each cell and performing a depth-first search (DFS) or breadth-first search (BFS) to check if it can reach both oceans. This would involve repeatedly exploring adjacent cells that are not higher than the current cell.
**Algorithm:**
1. For each cell `(r, c)` in the matrix:
2. Perform DFS/BFS to check if it can reach the Pacific Ocean.
3. Perform DFS/BFS to check if it can reach the Atlantic Ocean.
4. If it can reach both, add it to the result.
**Code (Python):**
```python
def pacific_atlantic_brute_force(heights):
if not heights or not heights[0]:
return []
m, n = len(heights), len(heights[0])
result = []
def can_reach(r, c, ocean, visited):
if ocean == 'pacific':
if r < 0 or c < 0:
return True
else:
if r == m or c == n:
return True
if r < 0 or r >= m or c < 0 or c >= n or (r, c) in visited:
return False
visited.add((r, c))
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < m and 0 <= nc < n and heights[nr][nc] <= heights[r][c]:
if can_reach(nr, nc, ocean, visited):
return True
visited.remove((r,c))
return False
for r in range(m):
for c in range(n):
pacific_visited = set()
atlantic_visited = set()
if can_reach(r, c, 'pacific', pacific_visited) and can_reach(r, c, 'atlantic', atlantic_visited):
result.append([r, c])
return result
The optimal approach leverages the fact that we can start from the oceans and flow inwards. This is more efficient because we only explore cells that can reach the ocean. We use two matrices to keep track of which cells can reach the Pacific and Atlantic oceans, respectively.
Algorithm:
pacific
and atlantic
, of the same dimensions as heights
, filled with False
.pacific
matrix.atlantic
matrix.(r, c)
, if both pacific[r][c]
and atlantic[r][c]
are True
, add it to the result.Code (Python):
def pacific_atlantic(heights):
if not heights or not heights[0]:
return []
m, n = len(heights), len(heights[0])
pacific = [[False] * n for _ in range(m)]
atlantic = [[False] * n for _ in range(m)]
def dfs(r, c, ocean, visited):
if (r, c) in visited:
return
visited.add((r, c))
ocean[r][c] = True
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < m and 0 <= nc < n and heights[nr][nc] >= heights[r][c]:
dfs(nr, nc, ocean, visited)
# Pacific Ocean
for r in range(m):
dfs(r, 0, pacific, set())
for c in range(n):
dfs(0, c, pacific, set())
# Atlantic Ocean
for r in range(m):
dfs(r, n - 1, atlantic, set())
for c in range(n):
dfs(m - 1, c, atlantic, set())
result = []
for r in range(m):
for c in range(n):
if pacific[r][c] and atlantic[r][c]:
result.append([r, c])
return result
Naive Solution:
(r, c)
, we perform DFS/BFS, which in the worst case, can visit all the cells in the matrix. Therefore the run time for each cell is O(m*n).Optimal Solution:
Thus the time complexity is O(m*n)
Naive Solution:
Optimal Solution:
pacific
and atlantic
, each of size m x n
, so the space complexity is O(m*n) for each matrix.heights
is empty or has zero dimensions, we should return an empty list.