Simple commented java solution with thinking progress O(n)
```\n/\n1.Naive solution:\n    Standard dfs, which means for each point, we check if it can reach both pacific and atlantic, \n    for each point, we can possib
```\n/*\n1.Naive solution:\n    Standard dfs, which means for each point, we check if it can reach both pacific and atlantic, \n    for each point, we can possibly check all the rest of points, O(m*n * m*n)\n\n2.A little improvement:\n    What about we 4 hash tables, they keep track of all the points we know so far that \n        can reach atlantic\n        cannot reach atlantic\n        can reach pacific\n        cannot reach pacific\n    It's doable, still hit TLE, although I didn't hit TLE when not submitting the code, but running it using the provided testing environment\n\n3.On the other hand, we can consider the flip side\n    We can let the pacific and atlantic ocean "flow into" the matrix as much as possible,\n    using 2 boolean arrays, one for each ocean. \n    The result are the points that are true in both boolean table\n*/\n\n\npublic class Solution {\n    public List<int[]> pacificAtlantic(int[][] matrix) {\n        List<int[]> result = new ArrayList<int[]>();\n        if(matrix.length == 0 || matrix[0].length == 0) return result;   \n        boolean[][] pacific = new boolean[matrix.length][matrix[0].length];  // the pacific boolean table\n        boolean[][] atlantic = new boolean[matrix.length][matrix[0].length]; // the atlantic booean table\n        //initially, all the top and left cells are flooded with pacific water\n        //and all the right and bottom cells are flooded with atlantic water\n        for(int i = 0; i < matrix.length; i++){\n            pacific[i][0] = true;\n            atlantic[i][matrix[0].length-1] = true;\n        }\n        for(int i = 0; i < matrix[0].length; i++){\n            pacific[0][i] = true;\n            atlantic[matrix.length-1][i] = true; \n        }\n        //we go around the matrix and try to flood the matrix from 4 side.\n        for(int i = 0; i < matrix.length; i++){\n            boolean[][] pacificVisited = new boolean[matrix.length][matrix[0].length];\n            boolean[][] atlanticVisited = new boolean[matrix.length][matrix[0].length];\n            water(pacific, pacificVisited, matrix, i,0);\n            water(atlantic, atlanticVisited, matrix, i, matrix[0].length - 1);            \n        }\n        for(int i = 0; i < matrix[0].length; i++){\n            boolean[][] pacificVisited = new boolean[matrix.length][matrix[0].length];\n            boolean[][] atlanticVisited = new boolean[matrix.length][matrix[0].length];\n            water(pacific, pacificVisited, matrix, 0,i);\n            water(atlantic, atlanticVisited, matrix, matrix.length - 1, i);            \n        }\n        //check the shared points among 2 tables\n        for(int i = 0; i < matrix.length; i++){\n            for(int j = 0; j < matrix[0].length; j++){\n                if(pacific[i][j] && atlantic[i][j]){\n                    int[] element = {i,j};\n                    result.add(element);\n                }\n            }\n        }\n        return result;\n    }\n    //the flood function\n    private void water(boolean[][] wet, boolean[][] visited, int[][] matrix, int i , int j){\n        wet[i][j] = true;\n        visited[i][j] = true;\n        int[] x = {0,0,1,-1};\n        int[] y = {1,-1,0,0};\n        for(int k = 0; k < 4; k++){\n            if(i+y[k] >= 0 && i+y[k] < matrix.length && j+x[k] >= 0 && j+x[k] < matrix[0].length \n                && !visited[i+y[k]][j+x[k]] && matrix[i+y[k]][j+x[k]] >= matrix[i][j]){\n                water(wet, visited, matrix, i+y[k], j+x[k]);\n            }\n        }\n    }\n}````\n\nP.S Sometimes you choose an option just because the alternative is just worse.....
[]