LintCode 778: Pacific Atlantic Water Flow (BFS好题)

  1. 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]);
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值