【leetcode】深度优先遍历之孤岛问题

岛屿的个数

leetcode 200. 岛屿的个数https://leetcode-cn.com/problems/number-of-islands/

思路: DFS,走过一个要改成-1。

class Solution:
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if len(grid) == 0:
            return 0
        m = len(grid)
        n = len(grid[0])
        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    res += 1
                    self.dfs(grid, i, j)
        return res
    
    def dfs(self,grid,i,j):
        grid[i][j] = '-1'
        orients = [[-1, 0], [1, 0], [0, -1], [0, 1]]
        for o in orients:
            p = i + o[0]
            q = j + o[1]
            if p >= 0 and q >= 0 and p < len(grid) and q < len(grid[0]) and grid[p][q] == '1':
                self.dfs(grid, p, q)
        return

岛屿最大面积(最大连通子图)

leetcode 695 岛屿最大面积:https://leetcode-cn.com/problems/max-area-of-island/submissions/

class Solution:
    def maxAreaOfIsland(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if len(grid) == 0:
            return 0
        m = len(grid)
        n = len(grid[0])
        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    area = self.dfs(grid, i, j)
                    res = max(res, area)
        return res
    
    def dfs(self, grid, i, j):
        area = 1
        grid[i][j] = -1 #表示已经走过
        orients = [[-1,0],[1,0],[0,-1],[0,1]]
        for o in orients:
            p = i + o[0]
            q = j + o[1]
            if p>= 0 and q >= 0 and p < len(grid) and q < len(grid[0]) and grid[p][q] == 1:
                area += self.dfs(grid,p,q)     
        return area

被围绕的区域

leetcode 130 被围绕的区域:https://leetcode-cn.com/problems/surrounded-regions/

首先对边界上每一个'O'做深度优先搜索,将与其相连的所有'O'改为'-'。然后遍历矩阵,将矩阵中所有'O'改为'X',将矩阵中所有'-'变为'O'

class Solution:
    def solve(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        if len(board) == 0:
            return
        m = len(board)
        n = len(board[0])
        #先把边界上的连通的O都刨去(变成-)
        for i in range(m):
            self.dfs(board, i, 0)
            self.dfs(board, i, n-1)
        for j in range(n):
            self.dfs(board, 0, j)
            self.dfs(board, m-1, j)
        #剩下的O肯定被X包围,将其变为X,最后记得把上面变成-的O再变回去
        for i in range(m):
            for j in range(n):
                if board[i][j] == 'O':
                    board[i][j] = 'X'
                elif board[i][j] == '-':
                    board[i][j] = 'O'
        return
    
    def dfs(self, board, i, j):
        if i >= 0 and j >= 0 and i < len(board) and j < len(board[0]) and board[i][j] == 'O':  
            board[i][j] = '-'
            orients = [(-1,0), (1,0), (0,-1),(0,1)]
            for o in orients:
                p = i + o[0]
                q = j + o[1]
                self.dfs(board, p, q)
        return

太平洋大西洋洋流问题

leetcode 417. 太平洋大西洋水流问题https://leetcode-cn.com/problems/pacific-atlantic-water-flow/

建立两个矩阵Atlantic和Pacific, 当Atlantic[i][j]和Pacific[i][j]同时为true时表示该位置可以同时到达Atlantic和Pacific
便历时的技巧为: 只需要从四个边界开始遍历即可(类似泛洪的思想, 只要可以从边界出发到达, 就说明该位置的水可以流向对应的海洋)

class Solution(object):
    def pacificAtlantic(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[List[int]]
        """
        #即找到边界是否能连通到哪些位置即可
        if len(matrix) == 0:
            return []
        m = len(matrix)
        n = len(matrix[0])
        pacific = [[False for _ in range(n)] for _ in range(m)]
        atlantic = [[False for _ in range(n)] for _ in range(m)]
        for i in range(m):
            self.dfs(matrix, i, 0, pacific, matrix[i][0])
            self.dfs(matrix, i, n-1, atlantic, matrix[i][n-1])
        for j in range(n):
            self.dfs(matrix, 0, j, pacific, matrix[0][j])
            self.dfs(matrix, m-1, j, atlantic, matrix[m-1][j])
        res = []
        for i in range(m):
            for j in range(n):
                if pacific[i][j] and atlantic[i][j]:
                    res.append([i,j])
        return res
    
    def dfs(self, matrix, i, j, visited, pre):
        if i >= 0 and i < len(matrix) and j >= 0 and j < len(matrix[0]) and (not visited[i][j]) and matrix[i][j] >= pre:
            visited[i][j] = True
            self.dfs(matrix, i-1, j, visited, matrix[i][j])
            self.dfs(matrix, i+1, j, visited, matrix[i][j])
            self.dfs(matrix, i, j-1, visited, matrix[i][j])
            self.dfs(matrix, i, j+1, visited, matrix[i][j])
        return

扫雷游戏

leetcode 529 扫雷:https://leetcode-cn.com/problems/minesweeper/

class Solution(object):
    def updateBoard(self, board, click):
        """
        :type board: List[List[str]]
        :type click: List[int]
        :rtype: List[List[str]]
        """
        if len(board) == 0:
            return []
        m = len(board)
        n = len(board[0])
        #先实现标记一下哪些点周围有地雷
        orients = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]
        visited = [[False for _ in range(n)] for _ in range(m)]#标记是否访问过
        nums = [[0 for _ in range(n)] for _ in range(m)]#标记每个点周围地雷的个数
        for i in range(m):
            for j in range(n):
                if board[i][j] == 'M':
                    for x, y in orients:
                        if i+x >= 0 and i+x < m and j+y >=0 and j+y < n:
                            nums[i+x][j+y] += 1
        self.dfs(board, click[0], click[1], nums, orients, visited)
        return board
        
    def dfs(self, board, i, j, nums, orients, visited):
        visited[i][j] = True
        if board[i][j] == 'M':
            board[i][j] = 'X'
            return
        if nums[i][j] > 0:
            board[i][j] = str(nums[i][j])
            return 
        if board[i][j] == 'E':
            board[i][j] = 'B'
            for x, y in orients:
                if i+x >= 0 and i+x < len(board) and j+y >=0 and j+y < len(board[0]) and not visited[i+x][j+y]:
                    self.dfs(board, i+x, j+y, nums, orients, visited)
        return
        

 

二叉树中距离为K的节点

leetcode 863 二叉树中所有距离为K的节点:https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/comments/

建图 + DFS

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

from collections import defaultdict
class Solution:
    def distanceK(self, root, target, K):
        """
        :type root: TreeNode
        :type target: TreeNode
        :type K: int
        :rtype: List[int]
        """
        if root is None:
            return []
        res = []
        g = defaultdict(list)
        self.buildGraph(None, root, g)#创建图
        visited = [target]#保存访问过的节点
        self.dfs(target, 0, K, res, visited, g)
        return res
    
    def buildGraph(self, parent, child, g):
        if parent:
            g[parent].append(child)
            g[child].append(parent)
        if child.left:
            self.buildGraph(child, child.left,g)
        if child.right:
            self.buildGraph(child, child.right,g)
    
    def dfs(self, start, i, K, res, visited, g):
        if start is None:
            return
        if i > K:
            return
        if i == K:
            res.append(start.val)
            return
        for node in g[start]:
            if node in visited:
                continue
            visited.append(node)
            self.dfs(node, i+1, K, res, visited, g)
            

马在棋盘上的概率

https://leetcode-cn.com/problems/knight-probability-in-chessboard/submissions/

class Solution:
    def knightProbability(self, N, K, r, c):
        """
        :type N: int
        :type K: int
        :type r: int
        :type c: int
        :rtype: float
        """
        cnt = 0
        dp0 = [[1 for i in range(N)] for j in range(N)]#代表每个位置可以由多少个点走k步到达
        orients = [(1,2),(1,-2),(-1,2),(-1,-2),(2,1),(2,-1),(-2,1),(-2,-1)]
        for _ in range(K):
            dp1 = [[0 for i in range(N)] for j in range(N)]
            for i in range(N):
                for j in range(N):
                    for x,y in orients:
                        p = i + x
                        q = j + y
                        if p>=0 and p<N and q>=0 and q<N:
                            dp1[i][j] += dp0[p][q]
            dp0 = dp1
        return dp0[r][c]/(8**K)
        

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章