【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)
        

 

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