Python solution with detailed explanation
Solution\n\nPacific Atlantic Water Flow https://leetcode.com/problems/pacific-atlantic-water-flow/\n\nBrute Force Solution\n For every point in the grid, find w
**Solution**\n\n**Pacific Atlantic Water Flow** https://leetcode.com/problems/pacific-atlantic-water-flow/\n\n**Brute Force Solution**\n* For every point in the grid, find whether it can reach both pacific and atlantic. You can use standard DFS or BFS for this. There are mn points and DFS/BFS is O(2mn).\n\n**Optimized Solution**\n* On the other hand, we can consider the flip side. We can let the pacific and atlantic ocean "flow into" the matrix as much as possible, using 2 boolean arrays, one for each ocean. The result are the points that are true in both boolean table.\n* Two Queue and add all the Pacific border to one queue; Atlantic border to another queue.\n* Keep a visited matrix for each queue. In the end, add the cell visited by two queue to the result.\n* Water flows from ocean to the cell. Since water can only flow from high/equal cell to low cell, **add the neighboor cell with height larger or equal to current cell to the queue and mark as visited**.\n```\nif 0<=x1<N and 0<=y1<M and not visited[x1][y1] and matrix[x1][y1] >= matrix[x][y]\n```\n* Note we can also use DFS here. Do a DFS from every pacific point and then from every atlantic point. Take an intersection later.\n* https://discuss.leetcode.com/topic/62280/simple-commented-java-solution-with-thinking-progress-o-n\n* https://discuss.leetcode.com/topic/62379/java-bfs-dfs-from-ocean\n\n```\nfrom Queue import Queue\nclass Solution(object):\n    def bfs(self, q, matrix, visited):\n        N, M  = len(matrix), len(matrix[0])\n        while q.empty() == False:\n            (x,y) = q.get()\n            candidates = [(x+1,y), (x-1,y), (x,y+1), (x,y-1)]\n            for (x1,y1) in candidates:\n                if 0<=x1<N and 0<=y1<M and not visited[x1][y1] and matrix[x1][y1] >= matrix[x][y]:\n                    q.put((x1,y1))\n                    visited[x1][y1]=True\n        return\n    \n    def initialize_q(self, N, M, pac_q, atl_q, pac_visited, atl_visited):\n        for i in range(N):\n            pac_q.put((i,0))\n            atl_q.put((i, M-1))\n            pac_visited[i][0], atl_visited[i][M-1] = True, True\n                        \n        for j in range(M):\n            pac_q.put((0,j))\n            atl_q.put((N-1,j))\n            pac_visited[0][j], atl_visited[N-1][j] = True, True\n        return\n    \n    def pacificAtlantic(self, matrix):\n        """\n        :type matrix: List[List[int]]\n        :rtype: List[List[int]]\n        """\n        if matrix == []:\n            return []\n        N, M  = len(matrix), len(matrix[0])\n        pac_q, atl_q = Queue(), Queue()\n        pac_visited = [[False]*M for _ in range(N)]\n        atl_visited = [[False]*M for _ in range(N)]        \n        \n        self.initialize_q(N, M, pac_q, atl_q, pac_visited, atl_visited)\n        self.bfs(pac_q, matrix, pac_visited)            \n        self.bfs(atl_q, matrix, atl_visited)            \n        \n        result = []\n        for i in range(N):\n            for j in range(M):\n                if pac_visited[i][j] and atl_visited[i][j]:\n                    result.append([i,j])\n                    \n        return result\n```
[]