题目
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。
规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。
请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。
提示:
输出坐标的顺序不重要
m 和 n 都小于150
示例:
给定下面的 5x5 矩阵:
太平洋 ~ ~ ~ ~ ~
~ 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 *
* * * * * 大西洋
返回:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上图中带括号的单元).
没有官方题解,看一看大佬的解法
方法一:
思路:
可以转换为海浪问题(从大海向大陆流向),问题就变简单了。
太平洋的海浪 和 大西洋的海浪 可以交汇的节点,
这些节点就既可以流向太平洋, 也可以流向大西洋
太平洋 ~ ~ ~ ~ ~
~ 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 *
* * * * * 大西洋
陆地,数字大小代表高度,海浪是从海洋倒灌到大陆高地。
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
P代表太平洋
P P P P P
P . . . .
P . . . .
P . . . .
P . . . .
A代表大西洋
. . . . A
. . . . A
. . . . A
. . . . A
A A A A A
太平洋的海浪,可以倒灌的区域。
P P P P P
P P P P P
P P P . .
P P . . .
P . . . .
大西洋的海浪,可以倒灌的区域。
. . . . A
. . . A A
. . A A A
A A A A A
A A A A A
到此,问题答案已经明晰了,
class Solution {
private int d[][] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
private List<List<Integer>> res;
private int r,c;
private boolean[][] pVisited,aVisited;
private final static int DIRECTION =4;
public List<List<Integer>> pacificAtlantic(int[][] matrix) {
res = new ArrayList<>();
if (matrix==null || matrix.length ==0 || matrix[0].length==0){
return res;
}
r=matrix.length;
c=matrix[0].length;
pVisited = new boolean[r][c];
aVisited = new boolean[r][c];
for (int i = 0; i <r ; i++) {
for (int j = 0; j <c ; j++) {
if (!pVisited[i][j] && inPacificCoast(i,j) ){
//从太平洋海边,随便一个地点海浪倒灌入陆地
pour(matrix,i,j,matrix[i][j],pVisited);
}
if (!aVisited[i][j] && inAtlanticCoast(i,j)){
//大西洋海边随便一个点海浪倒灌入陆地
pour(matrix,i,j,matrix[i][j],aVisited);
}
}
}
for (int i = 0; i < r; i++) {
for (int j = 0; j <c ; j++) {
if (pVisited[i][j] && aVisited[i][j]){
res.add(Arrays.asList(i,j));
}
}
}
return res;
}
private void pour(int[][] matrix, int x, int y, int h, boolean[][] v) {
v[x][y] =true;
for (int i = 0; i < DIRECTION; i++) {
int nextX = x+d[i][0];
int nextY = y+d[i][1];
if (inMatrix(nextX, nextY) && !v[nextX][nextY] && matrix[nextX][nextY] >= h) {
pour(matrix, nextX, nextY, matrix[nextX][nextY], v);
}
}
}
private boolean inMatrix(int x, int y) {
return x>=0 && x<r && y>=0 && y<c;
}
private boolean inAtlanticCoast(int x, int y) {
return (y==c-1 )||( x==r-1 );
}
private boolean inPacificCoast(int x, int y) {
return (x==0 )||(y==0 );
}
}
方法二:深度优先搜索
解题思路
主要问题,就是要知道退出搜索的条件和“满足流入海洋”的条件
一、对于太平洋
1、退出搜索的条件:
- a、已搜索到大西洋的边界,即坐标(i,j),其中i > matrix.length-1 || j > matrix[0].length-1
- b、当前位置已搜索过
- c、当前坐标的值大于上一个坐标的值
2、满足流入海洋的条件 - a、已搜索到太平洋的边界,即坐标(i,j),其中i <= 0 || j <= 0
一、对于大西洋
1、退出搜索的条件:
- a、已搜索到太平洋的边界,即坐标(i,j),其中i < 0 || j < 0
- b、当前位置已搜索过
- c、当前坐标的值大于上一个坐标的值
2、满足流入海洋的条件 - a、已搜索到大西洋的边界,即坐标(i,j),其中i >= matrix.length-1 || j >= matrix[0].length-1
class Solution {
public List<List<Integer>> pacificAtlantic(int[][] matrix) {
List<List<Integer>> res = new ArrayList<>();
if(matrix == null || matrix.length == 0){
return res;
}
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(dfsPacific(matrix,i,j,Long.MAX_VALUE)
&& dfsAtlantic(matrix,i,j,Long.MAX_VALUE)){
res.add(Arrays.asList(i,j));
}
}
}
return res;
}
//“太平洋”处于大陆的左边界和上边界
private boolean dfsPacific(int[][] matrix, int i, int j, long prev){
if(i > matrix.length-1 || j > matrix[0].length-1 || matrix[i][j] == -1 || matrix[i][j] > prev){
return false;
}
//到了太平洋的边界,说明可以流入,返回true
if(i <= 0 || j <= 0){
return true;
}
//临时记录当前matrix[i][j]的值,防止重复遍历
int temp = matrix[i][j];
matrix[i][j] = -1;
boolean result = dfsPacific(matrix,i-1,j,temp)
|| dfsPacific(matrix,i+1,j,temp)
|| dfsPacific(matrix,i,j-1,temp)
|| dfsPacific(matrix,i,j+1,temp);
matrix[i][j] = temp;
return result;
}
//“大西洋”处于大陆的右边界和下边界
private boolean dfsAtlantic(int[][] matrix, int i, int j, long prev){
if(i < 0 || j < 0 || matrix[i][j] == -1 || matrix[i][j] > prev){
return false;
}
//到了大西洋的边界,说明可以流入,返回true
if(i >= matrix.length-1 || j >= matrix[0].length-1){
return true;
}
//临时记录当前matrix[i][j]的值,防止重复遍历
int temp = matrix[i][j];
matrix[i][j] = -1;
boolean result = dfsAtlantic(matrix,i-1,j,temp)
|| dfsAtlantic(matrix,i+1,j,temp)
|| dfsAtlantic(matrix,i,j-1,temp)
|| dfsAtlantic(matrix,i,j+1,temp);
matrix[i][j] = temp;
return result;
}
}