417. Pacific Atlantic Water Flow

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

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

[
[1,2,3],
[8,9,4],
[7,6,5]
]

方法0: wrong

思路:

这道题本来用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;
    }
};

方法2: dfs

思路:

从所有边界点开始同步发起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;
    }
};

方法2: dfs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值