LeetCode题解随笔——DFS BFS相关题目 不断更新

LeetCode题解——BFS DFS

LC200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        def bfs(grid, r, c):
            from collections import deque
            queue = deque([])
            queue.append([r, c])
            while queue:
                r, c = queue.popleft()
                # 排除边界和访问过的
                if not (0<=r<len(grid) and 0<=c<len(grid[0])): continue
                if grid[r][c] == 'x': continue
                # 符合条件的 标记为已经访问
                grid[r][c] = 'x'
                for x, y in ([r+1,c],[r-1,c],[r,c+1],[r,c-1]):
                    queue.append([x,y])
                    
            # 从网格里的陆地开始遍历,遍历一遍就把连着的变成x,统一算作一个岛屿
            cnt = 0
            for i in range(len(grid)):
                for j in range(len(grid[0])):
                    if grid[i][j] == '1':
                        bfs(grid, i, j)
                        cnt += 1
            return cnt

LC695. 岛屿的最大面积

给你一个大小为 m x n 的二进制矩阵 grid 。

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        # DFS 从岛屿出发 将每个节点压栈 遇到返回条件开始弹出 计算面积
        def dfs(grid, r, c):
            area = 0
            # 设置返回条件
            if not (0<= r < len(grid) and 0<= c < len(grid[0])):
                return 0
            if grid[r][c] == 2:
                return 0
            # 标记
            grid[r][c] = 2
            # 递归寻找连着的陆地 统计进这块岛屿
            area += 1 + dfs(grid,r+1,c) + dfs(grid,r-1,c) + dfs(grid,r,c+1) + dfs(grid,r,c-1)
            return area
        
        area = 0
		for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    area = max(area, dfs(grid, i, j))
        return area

剑指 Offer 13. 机器人的运动范围

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
		def getSum(x):
            ans = 0
            while x > 0:
                ans += x%10
                x //= 10
            return ans
        
        visited = [[0]*n for _ in range(m)]
        def dfs(m, n, k, x, y, visited):
            
            # 设置返回条件
            if not (0<= x <m and 0<= y <n):
                return 0
            if visited[x][y] == 1:
                return 0
            # 数位之和大于k了也要标记为已经访问
            if getSum(x) + getSum(y) > k:
                visited[x][y] = 1
                return 0
            
            # 能访问就标记为已访问
            visited[x][y] = 1
            # 递归寻找其他点
            return 1 + dfs(m,n,k,x+1,y,visited) + dfs(m,n,k,x-1,y,visited) + dfs(m,n,k,x,y+1,visited) + dfs(m,n,k,x,y-1,visited)
        
        # 直接从起点00开始,一遍深搜就能计算出结果
        return dfs(m,n,k,0,0,visited)

LC417. 太平洋大西洋水流问题

给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。

请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。

class Solution:
    def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
        # 从内部的点出发遍历,计算量大会超时
        # 从太平洋边界出发,BFS遍历一遍,访问过的点,在stream数组上+1
        # 从大西洋边界出发,BFS遍历一遍,访问过的点,在stream数组上+1
        # 最后找到2的点就是坐标
        from collections import deque
        m, n = len(heights), len(heights[0])
        # 标记数组,0未被访问,1访问过
        visited = [[0] * n for _ in range(m)]
        stream = [[0] * n for _ in range(m)]
        
        def bfs(heights, x, y, visited):
            queue = deque([])
            queue.append([x, y])
            while queue:
                x, y = queue.popleft()

                if not(0<= x < len(heights) and 0<= y < len(heights[0])):
                    continue
                if visited[x][y] == 1:
                    continue
                
                # 到这里说明没问题
                visited[x][y] = 1
                stream[x][y] += 1

                for newx, newy in ([x+1, y],[x-1,y],[x,y+1],[x,y-1]):
                    # 后面要对比每个点的高度所以这里也要检查合法 否则数组会越界
                    if not (0<= newx < len(heights) and 0<= newy < len(heights[0])):
                        continue
                    if visited[newx][newy] == 1:
                        continue
                    # 逆流而上,高度大于等于的才加入队列,得把高度小的剔除掉
                    if heights[newx][newy] < heights[x][y]:
                        continue
                    queue.append([newx, newy])

        # 从太平洋边界出发遍历一遍
        for i in range(0, m):
            bfs(heights, i, 0, visited)
        for j in range(0, n):
            bfs(heights, 0, j, visited)

        # 重置visited,再从大西洋边界遍历一遍
        visited = [[0] * n for _ in range(m)]
        for i in range(0, m):
            bfs(heights, i, n-1, visited)
        for j in range(0, n):
            bfs(heights, m-1, j, visited)
            
        # 最后遍历一遍 找到数值为2的就是能流过去的
        ans = []
        for i in range(m):
            for j in range(n):
                if stream[i][j] == 2:
                    ans.append([i, j])
        return ans
上一篇:test


下一篇:bfs