题目
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:
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 *
* * * * * Atlantic
Return:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
解题思路
这道题目也是很典型的 BFS/DFS
题目,很自然会想到依次对每个点进行 BFS
看其是否既能到达太平洋又能到达大西洋,但是这种解法会导致超时,原因有:
- 对不能到达太平洋和大西洋的点也进行了一次
BFS
遍历,做了太多的无用功。 - 如果一个点能够到达某个海洋,则从这点到这个海洋的路径上的所有点也肯定能到达这个海洋,因此在对一个点进行
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));
}
}
}
};