LeetCode題解隨筆——DFS BFS相關題目 不斷更新
阿新 • • 發佈:2021-09-29
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