417. Pacific Atlantic Water Flow

417. Pacific Atlantic Water Flow

Medium

3734840Add to ListShare

There is an m x n rectangular island that borders both the Pacific Ocean and Atlantic Ocean. The Pacific Ocean touches the island's left and top edges, and the Atlantic Ocean touches the island's right and bottom edges.

The island is partitioned into a grid of square cells. You are given an m x n integer matrix heights where heights[r][c] represents the height above sea level of the cell at coordinate (r, c).

The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell's height is less than or equal to the current cell's height. Water can flow from any cell adjacent to an ocean into the ocean.

Return 2D list of grid coordinates result where result[i] = [ri, ci] denotes that rain water can flow from cell (ri, ci) to both the Pacific and Atlantic oceans.

Example 1:

Input: 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]]
Output: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

Example 2:

Input: heights = [[2,1],[1,2]]
Output: [[0,0],[0,1],[1,0],[1,1]]

Constraints:

  • m == heights.length
  • n == heights[r].length
  • 1 <= m, n <= 200
  • 0 <= heights[r][c] <= 105

class Solution:
    def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
        """
        assert Solution().pacificAtlantic([[1, 2, 3, 4],
                                       [12, 13, 14, 5],
                                       [11, 16, 15, 6],
                                       [10, 9, 8, 7]]) == [[0, 3], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1],
                                                           [2, 2], [2, 3], [3, 0], [3, 1], [3, 2], [3, 3]]
        assert Solution().pacificAtlantic([[1, 2, 3],
                                       [8, 9, 4],
                                       [7, 6, 5]]) == [[0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
        assert Solution().pacificAtlantic([[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]]
        assert Solution().pacificAtlantic([[2, 1],
                                       [1, 2]]) == [[0, 0], [0, 1], [1, 0], [1, 1]]
        assert Solution().pacificAtlantic([[1]]) == [[0, 0]]

        解题思路:题目理解了好久!也做了好久。最终还是不对。
        题目意思是打印所有坐标点,该坐标点的水能流到左上和右下,流通的规则是高于等于上下左右点的高度
        ------------------------------------------------
        我的不对的做法:
        一开始用dfs跑,要满足上面2个条件,处理起来状态很麻烦。写了好久好久。后面仔细一想分成2次递推
        第一次从左到右,推出当前坐标能否到达左上,用flag_l标记。同理
        第二次从右到左,推出当前坐标能否到达右下,用flag_r标记
        最后直把满足2个状态的条件得打印出来就行了
        ------------------------------------------------
        参考正确做法:还是用flag_l,flag_r标记 但是是从四周的点开始遍历,更新对应的flag状态

        时间复杂度:O(n*m) 空间复杂度:O(n*m)
        """

        # 深搜标记是否可达边界
        def dfsMark(x: int, y: int, flag: List[List[bool]]):
            if flag[x][y]:
                return

            # 标记可达
            flag[x][y] = True
            for i in dirt:
                nextX = x + i[0]
                nextY = y + i[1]
                if nextX < 0 or nextY < 0 or nextX > n - 1 or nextY > m - 1:
                    # 边界
                    continue
                if heights[nextX][nextY] >= heights[x][y] and flag[x][y]:
                    # 蔓延
                    dfsMark(nextX, nextY, flag)

        n, m = len(heights), len(heights[0])
        # 左上 右下
        dirt = [[-1, 0], [0, -1], [0, 1], [1, 0]]
        # 标记坐标状态 flag_l,flag_r 分别代表当前坐标能到左上,右下
        flag_l = [[False for j in range(m)] for i in range(n)]
        flag_r = [[False for j in range(m)] for i in range(n)]
        result = []

        # 从四周开始遍历
        for j in range(m):
            # 列 [0,m)
            dfsMark(0, j, flag_l)
            dfsMark(n - 1, m - 1 - j, flag_r)
        for i in range(n):
            # 行 [0,n)
            dfsMark(i, 0, flag_l)
            dfsMark(i, m - 1, flag_r)

        for i in range(n):
            for j in range(m):
                if flag_l[i][j] and flag_r[i][j]:
                    result.append([i, j])

        return result

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值