1. 程式人生 > 其它 >LeetCode題解隨筆——DFS BFS相關題目 不斷更新

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