417. Pacific Atlantic Water Flow

来源:互联网 发布:程序员培训机构 编辑:程序博客网 时间:2024/05/01 23:03

题目:

417. Pacific Atlantic Water Flow

DescriptionSubmissionsSolutions
  • Total Accepted: 11498
  • Total Submissions: 34789
  • Difficulty: Medium
  • Contributor: LeetCode

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:

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

Example:

Given the following 5x5 matrix:  Pacific ~   ~   ~   ~   ~        ~  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  *          *   *   *   *   * AtlanticReturn:[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).








解题思路:

这题与我之前做过的Number of Islands类似,都是将DFS运用在矩阵问题上。用DFS遍历矩阵,用两个boolean数组p和a来记录每个点是否可以到达太平洋和大西洋,然后递归地对它上下左右连通的点进行访问,直到走到边界处,将p[i][j]或a[i][j]的值赋1。若该点的下一个点能够与海洋连通,则该点也能与海洋相连。为了提高算法效率,可以在每次递归调用DFS之前先判断下一个点是否能与海洋连通,若可以则无需再调用DFS。

对一个点做完DFS之后如果p[i][j]和a[i][j]都为1则将其加入输出vector 


代码:

class Solution {public:int m, n;vector<pair<int, int>> res;bool p[150][150] = {0};bool a[150][150] = {0};    vector<pair<int, int>> pacificAtlantic(vector<vector<int>>& matrix) {    if(!res.empty())    res.clear();    if(matrix.empty())    return res;        m = matrix.size();        n = matrix[0].size();        for(int i = 0; i < m; i++){        for(int j = 0; j < n; j++){        DFS(matrix, i, j);        if(p[i][j] && a[i][j]){        pair<int, int> temp;        temp.first = i;        temp.second = j;        res.push_back(temp);        }        }        }        return res;    }    void DFS(vector<vector<int>>& matrix, int i, int j){    if(i == 0 || j == 0)    p[i][j] = 1;    if(i == m - 1 || j == n - 1)    a[i][j] = 1;    //up     if(i - 1 >= 0 && matrix[i - 1][j] <= matrix[i][j]){    if(p[i - 1][j])    p[i][j] = 1;    if(a[i - 1][j])    a[i][j] = 1;    if(!p[i - 1][j] && !a[i - 1][j]){    DFS(matrix, i - 1, j);     if(p[i - 1][j])    p[i][j] = 1;    if(a[i - 1][j])    a[i][j] = 1;    }    }    //down    if(i + 1 < m && matrix[i + 1][j] <= matrix[i][j]){    if(p[i + 1][j])    p[i][j] = 1;    if(a[i + 1][j])    a[i][j] = 1;    if(!p[i + 1][j] && !a[i + 1][j]){    DFS(matrix, i + 1, j);     if(p[i + 1][j])    p[i][j] = 1;    if(a[i + 1][j])    a[i][j] = 1;    }    }    //left    if(j - 1 >= 0 && matrix[i][j - 1] <= matrix[i][j]){    if(p[i][j - 1])    p[i][j] = 1;    if(a[i][j - 1])    a[i][j] = 1;    if(!p[i][j - 1] && !a[i][j - 1]){    DFS(matrix, i, j - 1);     if(p[i][j - 1])    p[i][j] = 1;    if(a[i][j - 1])    a[i][j] = 1;    }    }    //right    if(j + 1 < m && matrix[i][j + 1] <= matrix[i][j]){    if(p[i][j + 1])    p[i][j] = 1;    if(a[i][j + 1])    a[i][j] = 1;    if(!p[i][j + 1] && !a[i][j + 1]){    DFS(matrix, i, j - 1);     if(p[i][j + 1])    p[i][j] = 1;    if(a[i][j + 1])    a[i][j] = 1;    }        }    }};


其他答案:

做完之后看了一下solution里的解法发现可以倒过来想,把矩阵的边界点当做起点进行DFS,这样DFS树上的每一点都是可以到达海洋的,就不会存在我的做法中重复走的问题了。参考代码如下:

public class Solution {    public List<int[]> pacificAtlantic(int[][] matrix) {        List<int[]> res = new LinkedList<>();        if(matrix == null || matrix.length == 0 || matrix[0].length == 0){            return res;        }        int n = matrix.length, m = matrix[0].length;        boolean[][]pacific = new boolean[n][m];        boolean[][]atlantic = new boolean[n][m];        for(int i=0; i<n; i++){            dfs(matrix, pacific, Integer.MIN_VALUE, i, 0);            dfs(matrix, atlantic, Integer.MIN_VALUE, i, m-1);        }        for(int i=0; i<m; i++){            dfs(matrix, pacific, Integer.MIN_VALUE, 0, i);            dfs(matrix, atlantic, Integer.MIN_VALUE, n-1, i);        }        for (int i = 0; i < n; i++)             for (int j = 0; j < m; j++)                 if (pacific[i][j] && atlantic[i][j])                     res.add(new int[] {i, j});        return res;    }        int[][]dir = new int[][]{{0,1},{0,-1},{1,0},{-1,0}};        public void dfs(int[][]matrix, boolean[][]visited, int height, int x, int y){        int n = matrix.length, m = matrix[0].length;        if(x<0 || x>=n || y<0 || y>=m || visited[x][y] || matrix[x][y] < height)            return;        visited[x][y] = true;        for(int[]d:dir){            dfs(matrix, visited, matrix[x][y], x+d[0], y+d[1]);        }    }}


可以学习别人用二位数组来表示方向的方法,这样可以使得代码更加简洁。

除了DFS还可以使用BFS,使用两个队列即可,做法与DFS大同小异。

0 0
原创粉丝点击