太平洋大西洋水流问题

题目

给定一个 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]] (上图中带括号的单元).

DFS(depth-first search 深度优先遍历)

逆流判断,即从边缘开始向里面推进,比如以上边界太平洋为例,首先上边界的每个元素能流入太平洋,大陆内能如果存在一个元素,该元素能流入上边界任意一个元素,则该元素也能通过上边界流入太平洋。
针对任意一个有效(能通过上边界流入太平洋的)元素,将其视为树的根节点,其上下左右方向的四个元素视为树的子节点,如果这四个元素中存在元素、其值大于根节点,则将其视为新的根节点,并可以作为基准开始新的递归搜索。
在该问题,可以进行
在DFS递归的过程中,如果上下左右邻近方向的元素已经被判断为有效元素,则直接跳过该元素(即:该元素已经在其余的位置被访问且满足条件,小心迷宫问题的循环圈)
关于该思路为什么叫做DFS,如果代码书写时,是按着根节点的左右上下的顺序来访问并判断子节点,则程序在执行时,会先沿着某一有效方向,层层递归、直到访问到最深层、最后一个满足要求的节点,然后最深层、最后一个满足要求的节点会先完整地被判断其上下左右四个方向,然后再回溯,再倒数第二执行剩余方向的判断……,回溯……

代码

    def pacificAtlantic(self, matrix):
        if not any(matrix): return []
        # 流向太平洋的位置
        res1 = set()
        # 流向大西洋的位置
        res2 = set()
        row = len(matrix)
        col = len(matrix[0])
        
        # 从边界遍历
        
        def dfs(i, j, cur, res):
            res.add((i, j))
            for x, y in [[1, 0], [-1, 0], [0, 1], [0, -1]]:
                tmp_i = i + x
                tmp_j = j + y
                if 0 <= tmp_i < row and 0 <= tmp_j < col and matrix[i][j] <= matrix[tmp_i][tmp_j] and (tmp_i, tmp_j) not in res: 
                    dfs(tmp_i, tmp_j, matrix[i][j], res)
        # 太平洋
        for i in range(row):
            dfs(i, 0, 0, res1)
        # 太平洋
        for j in range(col):
            dfs(0, j, 0, res1)
        # 大西洋
        for i in range(row):
            dfs(i, col - 1, 0, res2)
        # 大西洋
        for j in range(col):
            dfs(row - 1, j, 0, res2)

        return res1 & res2

BFS广度优先遍历

从边缘往里推进,逆流,相比于DFS而言,BFS采用栈,先将太平洋对应的两条边缘的元素进行标记并均放入栈中,逐一取出栈中的元素,判断能流入该元素(该元素左右上下邻近方向的元素中比该元素大、且还未被标记)的压入栈,依次循环执行弹出、判断、压入栈,直到栈内元素为空。
该方法相比于DFS,遍历的层级是按着层级来展开的,即优先把同一层的每个根节点的四个方向先遍历,然后处理,处理之后压入栈,待上一层所有节点被遍历处理完之后,栈首的元素变为下一层所有的节点的第一个节点。

代码

def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:
    if not any(matrix): return []
    m, n = len(matrix), len(matrix[0])

    def bfs(q):
        res_set = set()
        while q:
            x, y = q.pop()
            res_set.add((x, y))
            for i, j in [(x+1, y), (x-1, y), (x, y-1), (x, y+1)]:
                if 0 <= i < m and 0 <= j < n and matrix[x][y] <= matrix[i][j] and (i, j) not in res_set:
                    q.append((i, j))
        return res_set
##list的合并直接使用+
    pacificq = [(0, j) for j in range(n)] + [(i, 0) for i in range(m)] #太平洋
    atlanticq = [(m-1, j) for j in range(n)] + [(i, n-1) for i in range(m)]
    return list(bfs(pacificq) & bfs(atlanticq))#交集

你可能感兴趣的:(刷刷刷,算法,数据结构,python,dfs,leetcode)