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 * AtlanticReturn:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
[ [1,2,3], [8,9,4], [7,6,5] ]
思路:
这道题本来用dp做,但是错了。因为dp假设了pacific的水一定从左上流过来,atlantic一定从右下流过来,那么直接两次dp找两条单调非递减路线即可。但跑了一次啊发现了如下反例: [ [1,2,3], [8,9,4], [7,6,5] ] Output [[2,2],[2,0],[1,2],[1,1],[1,0],[0,2]] Expected [[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]
事实证明为了到达[2, 1] , 海水是绕了弯的。所以还是只能用search。
class Solution { public: vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return {}; int m = matrix.size(), n = matrix[0].size(); vector<vector<int>> dp1(m, vector<int> (n, 0)), dp2 = dp1; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j ++) { if (i == 0 || j == 0) dp1[i][j] = 1; else { if (matrix[i][j] >= matrix[i - 1][j]) { dp1[i][j] |= dp1[i - 1][j]; } if (matrix[i][j] >= matrix[i][j - 1]) { dp1[i][j] |= dp1[i][j - 1]; } } } } for (int i = m - 1; i >= 0; i--) { for (int j = n -1; j >= 0; j --) { if (i == m - 1 || j == n - 1) dp2[i][j] = 1; else { if (matrix[i][j] >= matrix[i + 1][j]) { dp2[i][j] |= dp2[i + 1][j]; } if (matrix[i][j] >= matrix[i][j + 1]) { dp2[i][j] |= dp2[i][j + 1]; } } } } vector<vector<int>> result; for (int i = m - 1; i >= 0; i--) { for (int j = n -1; j >= 0; j --) { if (dp1[i][j] && dp2[i][j]) result.push_back({i, j}); } } return result; } };思路:
从所有边界点开始同步发起bfs,将能渗透到的点标记。经过两次不同的bfs后,找到matrix上可以同时和两个大洋联通的点收集进结果即可。
class Solution { public: vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return {}; int m = matrix.size(), n = matrix[0].size(); vector<vector<int>> dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; vector<vector<int>> pacific(m, vector<int>(n, 0)), atlantic = pacific; queue<vector<int>> q; // pacific first for (int i = 0; i < m; i++) { pacific[i][0] = 1; q.push({i, 0}); } for (int j = 1; j < n; j++) { pacific[0][j] = 1; q.push({0, j}); } bfs(matrix, pacific, q, dirs); // atlantic then for (int i = m - 1; i >= 0; i--) { atlantic[i][n - 1] = 1; q.push({i, n - 1}); } for (int j = n - 1; j >= 0; j--) { atlantic[m - 1][j] = 1; q.push({m - 1, j}); } bfs(matrix, atlantic, q, dirs); // collect result vector<vector<int>> result; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j ++) { if (pacific[i][j] && atlantic[i][j]) result.push_back({i, j}); } } return result; } void bfs(vector<vector<int>> & matrix, vector<vector<int>> & ocean, queue<vector<int>> & q, vector<vector<int>> & dirs){ int m = matrix.size(), n = matrix[0].size(); while (!q.empty()) { auto top = q.front(); q.pop(); for (auto dir: dirs) { int x = top[0] + dir[0], y = top[1] + dir[1]; if (x < 0 || x >= m || y < 0 || y >= n || ocean[x][y] || matrix[x][y] < matrix[top[0]][top[1]]) continue; ocean[x][y] = 1; q.push({x, y}); } } return; } };