python刷题-dfs & bfs

1.通过dfs或bfs遍历一个二维数组

1020. 飞地的数量

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1:

python刷题-dfs & bfs_第1张图片

输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

示例 2:

python刷题-dfs & bfs_第2张图片

输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 500
  • grid[i][j] 的值为 0 或 1
from collections import deque
from typing import List

# dfs
class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        row, colomn = len(grid), len(grid[0])
        visit = [[False]*colomn for _ in range(row)]
        def dfs(i, j):
            if i >= 0 and i <= row-1  and j >=0 and j<=colomn-1 and grid[i][j] and not visit[i][j]:
                visit[i][j] = True
                for x, y in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):
                    dfs(x, y)
            else:
                return
        for i in range(row):
            dfs(i, 0)
            dfs(i, colomn-1)
        for j in range(1, colomn-1):
            dfs(0, j)
            dfs(row-1, j)
        return sum(grid[i][j] if not visit[i][j] else 0 for i in range(row) for j in range(colomn))
        # 官方题解是这样写的,注意sum可以对布尔类型做运算
        # return sum(grid[i][j] and not vis[i][j] for i in range(1, m - 1) for j in range(1, n - 1))


# 官方dfs
class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        vis = [[False] * n for _ in range(m)]

        def dfs(r: int, c: int) -> None:
            if r < 0 or r >= m or c < 0 or c >= n or grid[r][c] == 0 or vis[r][c]:
                return
            vis[r][c] = True
            for x, y in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
                dfs(x, y)

        for i in range(m):
            dfs(i, 0)
            dfs(i, n - 1)
        for j in range(1, n - 1):
            dfs(0, j)
            dfs(m - 1, j)
        return sum(grid[i][j] and not vis[i][j] for i in range(1, m - 1) for j in range(1, n - 1))

# tip: sum函数可以对bool类型进行运算
a = (2==1 and not 3==1 for _ in range(10))
print([x for x in a])
print (sum([False, False]))  


# bfs
class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        row, colomn = len(grid), len(grid[0])
        visit = [[False]*colomn for _ in range(row)]  # dfs和bfs的关键
        d = deque()
        for i in range(row):
            for j in range(colomn):
                if i == 0 or j == 0 or i == row-1 or j == colomn-1:
                    if grid[i][j] == 1 and not visit[i][j]:
                        visit[i][j] = True
                        d.append((i, j))
        while d:       # 注意这个while循环不能写在这个if下面(结果不一样),也不知道为什么,下次注意吧,要先把要遍历的东西全放到队列里面去
            i, j = d.popleft()

            for x, y in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):
                if x >= 0 and x <= row - 1 and y >= 0 and y <= colomn - 1 and not visit[x][y] and grid[x][y]:
                    d.append((x, y))
                    visit[x][y] = True
        return sum(grid[i][j] and not visit[i][j] for i in range(1, row-1) for j in range(1, colomn-1))

2.对二叉树的遍历

注意:dfs对应着二叉树的三种递归遍历,bfs对应层序遍历

113. 路径总和 II

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例 1:

python刷题-dfs & bfs_第3张图片

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

示例 2:

python刷题-dfs & bfs_第4张图片

输入:root = [1,2,3], targetSum = 5
输出:[]

示例 3:

输入:root = [1,2], targetSum = 0
输出:[]

提示:

  • 树中节点总数在范围 [0, 5000] 内
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

 

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
# dfs
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:

        def dfs(root:Optional[TreeNode], target, path:List[int], mysum:int):
            if root:
                path.append(root.val)
                mysum += root.val
                if not root.right and not root.left and mysum == target:
                    ret.append(path[:])
                    """
                    这个一定要用切片,不然会发生错误(直接输出空的列表),我推测大概是因为在函数调用时,
                    直接append(path)是对原来的path的地址空间进行append 所以才会显示空的集合,而
                    path[:]相当于深拷贝了一个新的path,对这个新的path的操作就是在一个新的地址空间的
                    操作,不会被原地址空间的path影响
                    详看:https://leetcode-cn.com/problems/path-sum-ii/solution/lc113-fengwei2002-guan-yu-bu-li-jie-slic-hank/
                    例如a = [1,2,3]
                    b = a
                    c = a[:]
                    b.append(4)
                    c.append(5)
                    print(a) # [1, 2, 3, 4]
                    """
                dfs(root.left, target, path, mysum)
                dfs(root.right, target, path, mysum)  # 这两个递归函数内部是不会改变外面的mysum变量的值的
                path.pop()
                # mysum -= root.val  不需要这一步,因为mysum这个变量对于递归的dfs内层函数来说相当于全局变量

        ret = []
        path = []
        dfs(root, targetSum, path, 0)
        return ret

 

你可能感兴趣的:(学习经验记录,算法刷题,深度优先,python,算法)