Pacific-Atlantic water flow#

Levels: level-4
Data structures: graph
Algorithms: dfs, bfs

LeetCode

Description#

  • Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the “Pacific ocean” touches the left and top edges of the matrix and the “Atlantic ocean” touches the right and bottom edges.
  • Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.
  • Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.

Note:

  • The order of returned grid coordinates does not matter.
  • Both m and n are less than 150.

Example#

 1Input:
 2  Pacific ~   ~   ~   ~   ~
 3       ~  1   2   2   3  (5) *
 4       ~  3   2   3  (4) (4) *
 5       ~  2   4  (5)  3   1  *
 6       ~ (6) (7)  1   4   5  *
 7       ~ (5)  1   1   2   4  *
 8          *   *   *   *   * Atlantic
 9Output:
10[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]]
11(positions with parentheses in above matrix).

Python Solution#

 1class Solution(object):
 2    def pacificAtlantic(self, matrix):
 3        """
 4        :type matrix: List[List[int]]
 5        :rtype: List[List[int]]
 6        """
 7        if not matrix: return []
 8        self.directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
 9        m = len(matrix)
10        n = len(matrix[0])
11        p_visited = [[False for _ in range(n)] for _ in range(m)]
12
13        a_visited = [[False for _ in range(n)] for _ in range(m)]
14        result = []
15
16        for i in range(m):
17            # p_visited[i][0] = True
18            # a_visited[i][n-1] = True
19            self.dfs(matrix, i, 0, p_visited, m, n)
20            self.dfs(matrix, i, n - 1, a_visited, m, n)
21        for j in range(n):
22            # p_visited[0][j] = True
23            # a_visited[m-1][j] = True
24            self.dfs(matrix, 0, j, p_visited, m, n)
25            self.dfs(matrix, m - 1, j, a_visited, m, n)
26
27        for i in range(m):
28            for j in range(n):
29                if p_visited[i][j] and a_visited[i][j]:
30                    result.append([i, j])
31        return result
32
33    def dfs(self, matrix, i, j, visited, m, n):
34        # when dfs called, meaning its caller already verified this point
35        visited[i][j] = True
36        for dir in self.directions:
37            x, y = i + dir[0], j + dir[1]
38            if x < 0 or x >= m or y < 0 or y >= n or visited[x][
39                    y] or matrix[x][y] < matrix[i][j]:
40                continue
41            self.dfs(matrix, x, y, visited, m, n)