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:

  1. The order of returned grid coordinates does not matter.
  2. 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).

这道题给了我们一个二维数组,说是数组的左边和上边是太平洋,右边和下边是大西洋,假设水能从高处向低处流,问我们所有能流向两大洋的点的集合。刚开始博主没有理解题意,以为加括号的点是一条路径,连通两大洋的,但是看来看去感觉也不太对,后来终于明白了,是每一个点单独都有路径来通向两大洋。那么就是典型的搜索问题,我最开始想的是对于每个点都来搜索是否能到达边缘,只不过搜索的目标点不再是一个单点,而是所有的边缘点,照这种思路写出的代码无法通过 OJ 大数据集,那么就要想办法来优化代码,优化的方法跟之前那道 Surrounded Regions 很类似,都是换一个方向考虑问题,既然从每个点向中间扩散会 TLE,那么我们就把所有边缘点当作起点开始遍历搜索,然后标记能到达的点为 true,分别标记出 pacific 和 atlantic 能到达的点,那么最终能返回的点就是二者均为 true 的点。我们可以先用DFS来遍历二维数组,参见代码如下:

解法一:

class Solution {
public:
vector<pair<int, int>> pacificAtlantic(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
vector<pair<int, int>> res;
int m = matrix.size(), n = matrix[].size();
vector<vector<bool>> pacific(m, vector<bool>(n, false));
vector<vector<bool>> atlantic(m, vector<bool>(n, false));
for (int i = ; i < m; ++i) {
dfs(matrix, pacific, INT_MIN, i, );
dfs(matrix, atlantic, INT_MIN, i, n - );
}
for (int i = ; i < n; ++i) {
dfs(matrix, pacific, INT_MIN, , i);
dfs(matrix, atlantic, INT_MIN, m - , i);
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (pacific[i][j] && atlantic[i][j]) {
res.push_back({i, j});
}
}
}
return res;
}
void dfs(vector<vector<int>>& matrix, vector<vector<bool>>& visited, int pre, int i, int j) {
int m = matrix.size(), n = matrix[].size();
if (i < || i >= m || j < || j >= n || visited[i][j] || matrix[i][j] < pre) return;
visited[i][j] = true;
dfs(matrix, visited, matrix[i][j], i + , j);
dfs(matrix, visited, matrix[i][j], i - , j);
dfs(matrix, visited, matrix[i][j], i, j + );
dfs(matrix, visited, matrix[i][j], i, j - );
}
};

那么 BFS 的解法也可以做,用 queue 来辅助,开始把边上的点分别存入 queue 中,然后对应的 map 标记 true,然后开始 BFS 遍历,遍历结束后还是找 pacific 和 atlantic 均标记为 true 的点加入结果 res 中返回即可,参见代码如下:

解法二:

class Solution {
public:
vector<pair<int, int>> pacificAtlantic(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
vector<pair<int, int>> res;
int m = matrix.size(), n = matrix[].size();
queue<pair<int, int>> q1, q2;
vector<vector<bool>> pacific(m, vector<bool>(n, false)), atlantic = pacific;
for (int i = ; i < m; ++i) {
q1.push({i, });
q2.push({i, n - });
pacific[i][] = true;
atlantic[i][n - ] = true;
}
for (int i = ; i < n; ++i) {
q1.push({, i});
q2.push({m - , i});
pacific[][i] = true;
atlantic[m - ][i] = true;
}
bfs(matrix, pacific, q1);
bfs(matrix, atlantic, q2);
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (pacific[i][j] && atlantic[i][j]) {
res.push_back({i, j});
}
}
}
return res;
}
void bfs(vector<vector<int>>& matrix, vector<vector<bool>>& visited, queue<pair<int, int>>& q) {
int m = matrix.size(), n = matrix[].size();
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
while (!q.empty()) {
auto t = q.front(); q.pop();
for (auto dir : dirs) {
int x = t.first + dir[], y = t.second + dir[];
if (x < || x >= m || y < || y >= n || visited[x][y] || matrix[x][y] < matrix[t.first][t.second]) continue;
visited[x][y] = true;
q.push({x, y});
}
}
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/417

参考资料:

https://leetcode.com/problems/pacific-atlantic-water-flow/

https://leetcode.com/problems/pacific-atlantic-water-flow/discuss/90733/java-bfs-dfs-from-ocean

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 417. Pacific Atlantic Water Flow 太平洋大西洋水流的更多相关文章

  1. 417 Pacific Atlantic Water Flow 太平洋大西洋水流

    详见:https://leetcode.com/problems/pacific-atlantic-water-flow/description/ C++: class Solution { publ ...

  2. [LeetCode] Pacific Atlantic Water Flow 太平洋大西洋水流

    Given an m x n matrix of non-negative integers representing the height of each unit cell in a contin ...

  3. LeetCode 417. Pacific Atlantic Water Flow

    原题链接在这里:https://leetcode.com/problems/pacific-atlantic-water-flow/description/ 题目: Given an m x n ma ...

  4. 【LeetCode】417. Pacific Atlantic Water Flow 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/pacific- ...

  5. 417. Pacific Atlantic Water Flow

    正常做的,用了645MS..感觉DFS的时候剪枝有问题.. 为了剪枝可能需要标记一个点的4种情况: 1:滨临大西洋,所有太平洋来的点可以通过: 2:濒临太平洋,所有大西洋来的点可以通过: 3:都不濒临 ...

  6. [Swift]LeetCode417. 太平洋大西洋水流问题 | Pacific Atlantic Water Flow

    Given an m x n matrix of non-negative integers representing the height of each unit cell in a contin ...

  7. Leetcode: Pacific Atlantic Water Flow

    Given an m x n matrix of non-negative integers representing the height of each unit cell in a contin ...

  8. [LeetCode] Pacific Atlantic Water Flow 题解

    题意 题目 思路 一开始想用双向广搜来做,找他们相碰的点,但是发现对其的理解还是不够完全,导致没写成功.不过,后来想清楚了,之前的错误可能在于从边界点进行BFS,其访问顺序应该是找到下一个比当前那个要 ...

  9. Java实现 LeetCode 417 太平洋大西洋水流问题

    417. 太平洋大西洋水流问题 给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度."太平洋"处于大陆的左边界和上边界,而"大西洋"处于大陆的 ...

随机推荐

  1. CSS3实现文字描边的2种方法

    问题 最近遇到一个需求,需要实现文字的描边效果,如下图           解决方法一     首先想到去看CSS3有没有什么属性可以实现,后来被我找到了text-stroke     该属性是一个复 ...

  2. A Pattern Language for Parallel Programming

    The pattern language is organized into four design spaces.  Generally one starts at the top in the F ...

  3. java的Class<T>与类型信息

    类型是一个数据符号,代表着数据的内存布局和访问规则. default public <T> T xxxxx(Class<T> xclass) throws Exception ...

  4. C#面试基础知识点:值类型和引用类型(1)(填坑文)

    目录 前言 C#值类型和引用类型 基类(共同点) 值类型继承基类(不同点) 应用类型继承 技术经理的问题 值类型与引用类型都可以用Equals来比较吗? 如何将一个数组a的值赋予数组b然后对b做修改而 ...

  5. Python urllib与requests、XML和HTMLParser

    参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1019223241745024 Python 的内建模块urllib提供了一系列用于操作 ...

  6. mssql SQL Server 2008 阻止保存要求重新创建表的更改问题的设置方法

    解决方法: 工具-〉选项-〉左侧有个 设计器-〉表设计器和数据库设计器 -> 阻止保存要求重新创建表的更改(右侧) 把钩去掉即可.

  7. 先排序然后union all失效,mysql数据库多个表union all查询并排序的结果为什么错误

    mysql数据库多个表union all查询并排序的结果为什么错误? 群主,我想进行一个表的查询,先把表中某个字段的内容查出,然后其他的再排序,我用union all连接两个表的查询结果排序是错的 比 ...

  8. 别忘了在使用MES系统之前,还有关键一步!

    如果你是不熟悉工业自动化领域的专业人士,又或者是从IT或其他背景进入到操作技术(OT)领域的相关人士,那么我相信你不会后悔读到这篇文章. 我们都想做到智能化生产,想将MES系统,APS系统应用到生产过 ...

  9. redis高并发总结

    Redis是单线程的,省去了很多上下文切换线程的时间:(官方答案:因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽.既然单线程容易实现, ...

  10. Asp.net管道模型之(HttpModules 和 HttpHandler)

    上一节我们从大概范围介绍了管道模型的整体流程,我们从其中知道管道最重要的两大组件为:HttpModules 跟 HttpHandler.今天我们着重来介绍一下这两大组件 一:asp.net处理管道 从 ...