题目
解析
这道题肯定第一时间想到的是dfs。但是这边如果遍历数组的每个位置进行dfs的话,复杂度太高了,这样做理论上时间复杂度会是O((MN)(M*N))。所以可以采用一种逆向的思路。从靠近大洋的四条边开始反向搜索,反向搜索的过程中把能够到的位置进行标记。如果某个位置两个大洋同时都能到,那么这个位置满足条件。这样的复杂度就是O((M+N)*MN).
二刷解法,更简洁
class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
can_reach_pacific = self.can_reach(heights,'pacific')
can_reach_atlan = self.can_reach(heights,'atlan')
ans = []
for i in range(len(heights)):
for j in range(len(heights[0])):
if can_reach_pacific[i][j] and can_reach_atlan[i][j]:
ans.append([i,j])
return ans
def can_reach(self,heights,ocean):
m,n = len(heights),len(heights[0])
can_reach = [[False]*n for _ in range(m)]
visited = [[False]*n for _ in range(m)]
q = collections.deque()
if ocean == 'pacific':
for i in range(m):
can_reach[i][0] = True
q.append((i,0))
visited[i][0] = True
for i in range(n):
can_reach[0][i] = True
q.append((0,i))
visited[0][i] = True
else:
for i in range(m):
can_reach[i][n-1] = True
q.append((i,n-1))
visited[i][n-1] = True
for i in range(n):
can_reach[m-1][i] = True
q.append((m-1,i))
visited[m-1][i] = True
dirs = [[1,0],[-1,0],[0,1],[0,-1]]
while q:
i,j = q.popleft()
for d in dirs:
x = i + d[0]
y = j + d[1]
if 0 <= x < m and 0 <= y < n and not visited[x][y] and heights[x][y] >= heights[i][j]:
q.append((x,y))
can_reach[x][y] = True
visited[x][y] = True
return can_reach
python代码:这边不知道咋的复制过来格式一直出错,就截图将就看吧
当然BFS也是能做的:
class Solution:
def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:
if not matrix or not matrix[0]:
return []
def helper(ocean,i,j):
ocean[i][j] = True
q = collections.deque()
q.append((i,j))
while q:
curr_pos = q.popleft()
dirs = [[0,1],[0,-1],[-1,0],[1,0]]
for d in dirs:
x = curr_pos[0]+d[0]
y = curr_pos[1]+d[1]
if 0<=x<len(ocean) and 0<=y<len(ocean[0]) and matrix[x][y]>=matrix[curr_pos[0]][curr_pos[1]] and not ocean[x][y]:
q.append((x,y))
ocean[x][y] = True
m = len(matrix)
n = len(matrix[0])
pacific = [[False]*n for _ in range(m)]
atlantic = [[False]*n for _ in range(m)]
for i in range(m):
helper(pacific,i,0)
helper(atlantic,i,n-1)
for i in range(n):
helper(pacific,0,i)
helper(atlantic,m-1,i)
ans = []
for i in range(m):
for j in range(n):
if pacific[i][j] and atlantic[i][j]:
ans.append((i,j))
return ans
C++版本如下:
class Solution {
public:
vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return {};
const int M = matrix.size();
const int N = matrix[0].size();
vector<vector<bool>> can_reach_p(M,vector<bool>(N));
vector<vector<bool>> can_reach_a(M,vector<bool>(N));
vector<vector<int>> ans;
for (int i=0;i<M;++i){
dfs(matrix,can_reach_p,i,0);
dfs(matrix,can_reach_a,i,N-1);
}
for (int i=0;i<N;++i){
dfs(matrix,can_reach_p,0,i);
dfs(matrix,can_reach_a,M-1,i);
}
for (int i=0;i<M;++i){
for (int j=0;j<N;++j){
if (can_reach_p[i][j] && can_reach_a[i][j]) {
ans.push_back({i,j});
}
}
}
return ans;
}
void dfs(const vector<vector<int>>& matrix, vector<vector<bool>>& can_reach, int i,int j){
can_reach[i][j] = true;
vector<pair<int,int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
for (auto d:dirs){
int x = i+d.first;
int y = j+d.second;
if (x<0 || x>=matrix.size() || y<0 || y>=matrix[0].size() || matrix[x][y]<matrix[i][j] || can_reach[x][y]){
continue;
}
dfs(matrix,can_reach,x,y);
}
}
};