LeetCode #417 Pacific Atlantic Water Flow

来源:互联网 发布:怎么创造软件 编辑:程序博客网 时间:2024/06/05 00:42

题目

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).

解题思路

这道题目也是很典型的 BFS/DFS 题目,很自然会想到依次对每个点进行 BFS 看其是否既能到达太平洋又能到达大西洋,但是这种解法会导致超时,原因有:

  1. 对不能到达太平洋和大西洋的点也进行了一次 BFS 遍历,做了太多的无用功。
  2. 如果一个点能够到达某个海洋,则从这点到这个海洋的路径上的所有点也肯定能到达这个海洋,因此在对一个点进行 BFS 遍历时就能同时确定多个点到某个海洋的可达性,显然对每个点进行 BFS 的解法无法利用这一个特性。

转换一下思路,我们从目标出发去寻找。可以从与太平洋和大西洋直接相邻的点(也就是矩阵边缘上的点)出发进行 BFS 去遍历矩阵中所有的点,则遍历到的点肯定是能够到达某个海洋的点!

具体的做法是维护两个 bool 数组 pacific[m][n]atlantic[m][n]pacific[i][j] == true 表示从太平洋边缘上的点进行 BFS 能够到达点 {i, j} ,即点 {i, j} 能够到达太平洋,对于大西洋的数组也同理。

到最后,把 使得pacific[i][j] == true && atlantic[i][j] == true 的点 {i, j} 加入到结果中即可。

C++代码实现

class Solution {public:    vector<pair<int, int>> pacificAtlantic(vector<vector<int>>& matrix) {        vector<pair<int, int> > rst;        if (matrix.size() == 0 || matrix[0].size() == 0) { return rst; }        int numOfRows = matrix.size(), numOfCols = matrix[0].size();        vector<vector<bool> > pacific(numOfRows, vector<bool>(numOfCols, false));        vector<vector<bool> > atlantic(numOfRows, vector<bool>(numOfCols, false));        queue<pair<int, int> > pQueue;        queue<pair<int, int> > aQueue;        for (int i = 0; i < numOfRows; ++i) {            pQueue.push(make_pair(i, 0));            aQueue.push(make_pair(i, numOfCols - 1));            pacific[i][0] = true;            atlantic[i][numOfCols - 1] = true;        }        for (int i = 0; i < numOfCols; ++i) {            pQueue.push(make_pair(0, i));            aQueue.push(make_pair(numOfRows - 1, i));            pacific[0][i] = true;            atlantic[numOfRows - 1][i] = true;        }        BFS(matrix, pQueue, pacific);        BFS(matrix, aQueue, atlantic);        for (int i = 0; i < numOfRows; ++i) {            for (int j = 0; j < numOfCols; ++j) {                if (pacific[i][j] && atlantic[i][j]) { rst.push_back(make_pair(i, j)); }            }        }        return rst;    }    void BFS(vector<vector<int>>& matrix, queue<pair<int, int> >& Q, vector<vector<bool> >& visited) {        int dir[4][2] = { {-1, 0}, { 0, 1 }, { 1, 0 }, {0, -1} };        while (!Q.empty()) {            pair<int, int> cur = Q.front();            Q.pop();            for (int i = 0; i < 4; ++i) {                int x = cur.first + dir[i][0];                int y = cur.second + dir[i][1];                if (x < 0 || x >= matrix.size() || y < 0 || y >= matrix[0].size() ||                    matrix[x][y] < matrix[cur.first][cur.second] || visited[x][y]) {                    continue;                }                visited[x][y] = true;                Q.push(make_pair(x, y));            }        }    }};