目录
1. 题目描述
有一个 m × n
的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。
这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n
的整数矩阵 heights
, heights[r][c]
表示坐标 (r, c)
上单元格 高于海平面的高度 。
岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。
返回 网格坐标 result
的 2D列表 ,其中 result[i] = [ri, ci]
表示雨水可以从单元格 (ri, ci)
流向 太平洋和大西洋 。
示例 1:
输入: heights = [[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]]
示例 2:
输入: heights = [[2,1],[1,2]] 输出: [[0,0],[0,1],[1,0],[1,1]]
提示:
m == heights.length
n == heights[r].length
1 <= m, n <= 200
0 <= heights[r][c] <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pacific-atlantic-water-flow
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题分析
这道题目的描述有一点点含糊的地方。应该是要找岛上的水既能流向太平洋又能流向大西洋的岛屿。
左下和右上两个岛显然都满足条件。
上边和左边两条边上的岛显然可以到达太平洋,而右边和下边两条边上的岛显然可以到达大西洋。但是各自能否到达另一个大洋需要查询。
显然这是一个可到达性的问题(reachability),但是也不是一个单纯的单源可到达性问题,而是像leetcode1162一样属于多源问题。
考虑从上、左两条边上的岛出发搜索能到达太平洋的岛屿连通区域,其中邻接岛屿定义为能够按照题设规则到达本岛的上下左右的岛,记所得的联通集合为islandSet1。
考虑从下、右两条边上的岛出发搜索能到达太平洋的岛屿连通区域,记所得的联通集合为islandSet2。
islandSet1和islandSet2的交集即为所求集合。
需要是需要遍历所有格点,所有广度优先搜索和深度优先搜索都可以。
需要注意的是,每个格点可能需要经过多次判断才能被判断能够加入connected,因为,一个格点有可能通过四个方向的任何一个方向与当前连通区域连通。所以,这里不需要或者不能用常规的访问过依次就加入其中的visited。connected1(2)就起到visited管理的作用。
3. 代码实现
from typing import List
from collections import deque
class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
R,C = len(heights),len(heights[0])
q = deque([(0,k) for k in range(C)] + [(k,0) for k in range(1,R)])
connected1 = set([(0,k) for k in range(C)] + [(k,0) for k in range(1,R)])
while len(q) > 0:
r,c = q.popleft()
for x,y in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
if 0<=x<R and 0<=y<C and (x,y) not in connected1:
if heights[x][y] >= heights[r][c]:
connected1.add((x,y))
q.append((x,y))
print(connected1)
q = deque([(R-1,k) for k in range(C)] + [(k,C-1) for k in range(R-1)])
connected2 = set([(R-1,k) for k in range(C)] + [(k,C-1) for k in range(R-1)])
while len(q) > 0:
r,c = q.popleft()
for x,y in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
if 0<=x<R and 0<=y<C and (x,y) not in connected2:
if heights[x][y] >= heights[r][c]:
connected2.add((x,y))
q.append((x,y))
print(connected2)
return list(connected2.intersection(connected1))
if __name__ == '__main__':
sln = Solution()
heights = [[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]]
print(sln.pacificAtlantic(heights))
heights = [[2,1],[1,2]]
print(sln.pacificAtlantic(heights))
执行用时:72 ms, 在所有 Python3 提交中击败了94.03%的用户
内存消耗:16.3 MB, 在所有 Python3 提交中击败了71.30%的用户
比较自豪的一个结果。
补充@2022-04-27
本题在之前图论基础学习计划中做过,但是每日一题要求也必须重新提交了一下。于是没有做任何代码重新提交了一下,结果如下:
执行用时:84 ms, 在所有 Python3 提交中击败了81.17%的用户
内存消耗:16.1 MB, 在所有 Python3 提交中击败了93.83%的用户
这个排名数据的变化情况令我很惊讶。两项相对数据发生变化可以理解,执行用时嘛,跟服务器的当前负荷有关发生变化也可以理解?关键是“内存消耗”这一个数据,这个数据是一个绝对的量,代码没有变化,按道理来说应该是没有变化的。很好奇力扣的结果评估机制是什么。