- Pacific Atlantic Water Flow
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.
Example
Example 1:
Input:
matrix =
[[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]]
Output:
[[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
Explanation:
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
Example 2:
Input:
matrix =
[[1,2],
[4,3]]
Output:
[[0,1],[1,0],[1,1]]
Notice
1.The order of returned grid coordinates does not matter.
2.Both m and n are less than 150.
解法1:BFS。
用两个queue,把周边的点先加入queue,最后比较一下两个queue中的相同点。
代码如下:
struct Node {
int x;
int y;
Node(int row = 0, int col = 0) : x(row), y(col) {}
};
class Solution {
public:
/**
* @param matrix: the given matrix
* @return: The list of grid coordinates
*/
vector<vector<int>> pacificAtlantic(vector<vector<int>> &matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<int> dx = {0, 0, 1, -1};
vector<int> dy = {1, -1, 0, 0};
vector<vector<int>> result;
queue<Node> pacificQ, atlanticQ;
vector<vector<bool>> pacificGrid(m, vector<bool>(n, false));
vector<vector<bool>> atlanticGrid(m, vector<bool>(n, false));
for (int i = 0; i < m; ++i) {
pacificQ.push(Node(i, 0));
pacificGrid[i][0] = 1;
atlanticQ.push(Node(i, n -1));
atlanticGrid[i][n - 1] = 1;
}
for (int j = 0; j < n; ++j) {
pacificQ.push(Node(0, j));
pacificGrid[0][j] = true;
atlanticQ.push(Node(m - 1, j));
atlanticGrid[m - 1][j] = true;
}
while(!pacificQ.empty()) {
Node node = pacificQ.front();
pacificQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n
&& !pacificGrid[newX][newY] && matrix[node.x][node.y] <= matrix[newX][newY]) {
Node tmpNode = Node(newX, newY);
pacificQ.push(tmpNode);
pacificGrid[newX][newY] = true;
}
}
}
while(!atlanticQ.empty()) {
Node node = atlanticQ.front();
atlanticQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n && !atlanticGrid[newX][newY] && matrix[node.x][node.y] <= matrix[newX][newY]) {
Node tmpNode = Node(newX, newY);
atlanticQ.push(tmpNode);
atlanticGrid[newX][newY] = true;
}
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (pacificGrid[i][j] && atlanticGrid[i][j]) result.push_back({i,j});
}
}
return result;
}
};
解法2:用unordered_set,然后看两个set的重合部分。
注意:unordered_set是基于hash table,所以要重载operator == (不需要重载opertor <),并且要定义NodeHash结构体,这样hash table才知道调用哪个hash function。
代码如下:
struct Node {
int x;
int y;
Node(int row = 0, int col = 0) : x(row), y(col) {}
bool operator == (const Node & n) const {
return x == n.x && y == n.y;
}
};
struct NodeHash {
int operator() (const Node & n) const {
return n.x * 33 + n.y;
}
};
class Solution {
public:
/**
* @param matrix: the given matrix
* @return: The list of grid coordinates
*/
vector<vector<int>> pacificAtlantic(vector<vector<int>> &matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<int> dx = {0, 0, 1, -1};
vector<int> dy = {1, -1, 0, 0};
vector<vector<int>> result;
queue<Node> pacificQ, atlanticQ;
unordered_set<Node, NodeHash> pacificS, atlanticS;
for (int i = 0; i < m; ++i) {
pacificQ.push(Node(i, 0));
pacificS.insert(Node(i, 0));
atlanticQ.push(Node(i, n - 1));
atlanticS.insert(Node(i, n - 1));
}
for (int j = 0; j < n; ++j) {
pacificQ.push(Node(0, j));
pacificS.insert(Node(0, j));
atlanticQ.push(Node(m - 1, j));
atlanticS.insert(Node(m - 1, j));
}
while(!pacificQ.empty()) {
Node node = pacificQ.front();
pacificQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n && pacificS.find(Node(newX, newY)) == pacificS.end() && matrix[node.x][node.y] <= matrix[newX][newY]) {
pacificQ.push(Node(newX, newY));
pacificS.insert(Node(newX, newY));
}
}
}
while(!atlanticQ.empty()) {
Node node = atlanticQ.front();
atlanticQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n && atlanticS.find(Node(newX, newY)) == atlanticS.end() && matrix[node.x][node.y] <= matrix[newX][newY]) {
atlanticQ.push(Node(newX, newY));
atlanticS.insert(Node(newX, newY));
}
}
}
for (auto node : pacificS) {
//for (auto it = pacificS.begin(); it != pacificS.end(); ++it) {
if (atlanticS.find(node) != atlanticS.end()) {
result.push_back({node.x, node.y});
}
}
return result;
}
};
解法3:顺便写了一个set的版本。不过set的操作太慢,这个版本会超时。
注意:
1)对于set的元素是结构体的情况,必须重载<,并且必须考虑每个字段的情况,如果只写成以下
bool operator < (const Node & n) const {
return x < n.x;
}
,那么set会把所有y相等的节点当成同一个元素!大错!
代码如下:
struct Node {
int x;
int y;
int z;
Node(int row = 0, int col = 0, int value = 0) : x(row), y(col), z(value) {}
bool operator < (const Node & n) const {
if (x < n.x) return true;
if (x == n.x && y < n.y) return true;
if (x == n.x && y == n.y) return z < n.z;
}
};
class Solution {
public:
/**
* @param matrix: the given matrix
* @return: The list of grid coordinates
*/
vector<vector<int>> pacificAtlantic(vector<vector<int>> &matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<int> dx = {0, 0, 1, -1};
vector<int> dy = {1, -1, 0, 0};
vector<vector<int>> result;
queue<Node> pacificQ, atlanticQ;
//unordered_set<Node, NodeHash> pacificS, atlanticS;
set<Node> pacificS, atlanticS;
for (int i = 0; i < m; ++i) {
pacificQ.push(Node(i, 0, matrix[i][0]));
pacificS.insert(Node(i, 0, matrix[i][0]));
atlanticQ.push(Node(i, n - 1, matrix[i][n - 1]));
atlanticS.insert(Node(i, n - 1, matrix[i][n - 1]));
}
for (int j = 0; j < n; ++j) {
pacificQ.push(Node(0, j, matrix[0][j]));
pacificS.insert(Node(0, j, matrix[0][j]));
atlanticQ.push(Node(m - 1, j, matrix[m - 1][j]));
atlanticS.insert(Node(m - 1, j, matrix[m - 1][j]));
}
while(!pacificQ.empty()) {
Node node = pacificQ.front();
pacificQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
Node tmpNode = Node(newX, newY, matrix[newX][newY]);
if (pacificS.find(tmpNode) == pacificS.end() && matrix[node.x][node.y] <= matrix[newX][newY]) {
pacificQ.push(tmpNode);
pacificS.insert(tmpNode);
}
}
}
}
while(!atlanticQ.empty()) {
Node node = atlanticQ.front();
atlanticQ.pop();
for (int i = 0; i < 4; ++i) {
int newX = node.x + dx[i];
int newY = node.y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
Node tmpNode = Node(newX, newY, matrix[newX][newY]);
if (atlanticS.find(tmpNode) == atlanticS.end() && matrix[node.x][node.y] <= matrix[newX][newY]) {
atlanticQ.push(tmpNode);
atlanticS.insert(tmpNode);
}
}
}
}
for (auto node : pacificS) {
if (atlanticS.find(node) != atlanticS.end()) {
result.push_back({node.x, node.y});
}
}
return result;
}
};
解法4:也可以用DFS。以下是网上的代码。
class Solution {
public:
/**
* @param matrix: the given matrix
* @return: The list of grid coordinates
*/
vector<vector<int>> pacificAtlantic(vector<vector<int>> &matrix) {
// write your code here
vector<vector<int>> res;
int n = matrix.size();
if(n == 0){
return res;
}
int m = matrix[0].size();
vector<vector<bool>> Pacific(n,vector<bool>(m,false));
vector<vector<bool>> Atlantic(n,vector<bool>(m,false));
for(int i = 0;i < n;i++){
dfs(matrix, Pacific, INT_MIN, i, 0);
dfs(matrix, Atlantic, INT_MIN, i, m - 1);
}
for(int i = 0;i < m;i++){
dfs(matrix, Pacific, INT_MIN, 0, i);
dfs(matrix, Atlantic, INT_MIN, n - 1, i);
}
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
if(Pacific[i][j] && Atlantic[i][j]){
vector<int> temp;
temp.push_back(i);
temp.push_back(j);
res.push_back(temp);
}
}
}
return res;
}
int dx[4] = {0,-1,0,1};
int dy[4] = {1,0,-1,0};
void dfs(vector<vector<int>> &matrix, vector<vector<bool>> &visited, int height, int x, int y){
int n = matrix.size();
int m = matrix[0].size();
if(x < 0 || x >=n || y < 0 || y >= m || matrix[x][y] < height || visited[x][y]){
return;
}
visited[x][y] = true;
for(int i = 0;i < 4;i++){
dfs(matrix, visited, matrix[x][y], x + dx[i], y + dy[i]);
}
}
};