在二维平面上使用回溯算法
79. 单词搜索(中等)
DFS 和状态重置
class Solution:
steps = [(0,1),(0,-1),(1,0),(-1,0)]
def exist(self, board: List[List[str]], word: str) -> bool:
if not board or not board[0]:
return False
rows = len(board)
cols = len(board[0])
visited = [[0 for _ in range(cols)] for _ in range(rows)]
for i in range(rows):
for j in range(cols):
if board[i][j]==word[0] and visited[i][j]==0:
visited[i][j]=1
if self.dfs(board,visited,word[1:],i,j):
return True
visited[i][j]=0
return False
def dfs(self,board,visited,word,i,j):
if not word:
return True
for step in self.steps:
x = i+step[0]
y = j+step[1]
if x>=0 and x<len(board) and y>=0 and y<len(board[0]) \
and board[x][y]==word[0] and visited[x][y]==0:
visited[x][y] = 1
if self.dfs(board,visited,word[1:],x,y):
return True
visited[x][y] = 0
return False
Floodfill,一类经典问题
200. 岛屿数量(中等)
200. 岛屿数量
方法一:DFS
class Solution:
steps = [(0,1),(0,-1),(1,0),(-1,0)]
def numIslands(self, grid: List[List[str]]) -> int:
if not grid or not grid[0]:
return 0
rows = len(grid)
cols = len(grid[0])
visited = [[0 for _ in range(cols)] for _ in range(rows)]
res = 0
for i in range(rows):
for j in range(cols):
if grid[i][j]=='1' and visited[i][j]==0:
visited[i][j]=1
res += 1
self.dfs(grid,visited,i,j)
return res
def dfs(self,grid,visited,i,j):
for step in self.steps:
x = i+step[0]
y = j+step[1]
if x>=0 and x<len(grid) and y>=0 and y<len(grid[0]) \
and grid[x][y]=='1' and visited[x][y]==0:
visited[x][y] = 1
self.dfs(grid,visited,x,y)
return
已经访问过的格子不能再访问一次,与79的区别
复杂度分析
时间复杂度:O(MN),其中 M 和 N 分别为行数和列数。
空间复杂度:O(MN),在最坏情况下,整个网格均为陆地,深度优先搜索的深度达到 M*N。
方法二:BFS
BFS搭配辅助队列
加入队列即标记为已读
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid or not grid[0]:
return 0
rows = len(grid)
cols = len(grid[0])
visited = [[0 for _ in range(cols)] for _ in range(rows)]
queue = []
res = 0
steps = [(0,1),(0,-1),(1,0),(-1,0)]
for i in range(rows):
for j in range(cols):
if grid[i][j]=='1' and visited[i][j]==0:
queue.append((i,j))
visited[i][j] = 1
res += 1
while queue:
x,y = queue.pop(0)
for step in steps:
x1 = x+step[0]
y1 = y+step[1]
if x1>=0 and x1<rows and y1>=0 and y1<cols \
and grid[x1][y1]=='1' and visited[x1][y1]==0:
queue.append((x1,y1))
visited[x1][y1] = 1
return res
复杂度分析
时间复杂度:O(MN),其中 M 和 N 分别为行数和列数。
空间复杂度:O(MN),visited数组M*N;在最坏情况下,整个网格均为陆地,队列的大小可以达到min(M,N)。
方法三:并查集
TODO
130. 被围绕的区域(中等)
130. 被围绕的区域
思路:
边界上的’O’或与边界上的’O’相连的’O’不会被填充,因此先找出这些’O’,赋值为’#‘以区分。
把剩下的’O’填充为’X’,把’#‘还原为’O’。
BFS
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if not board or not board[0]:
return
rows = len(board)
cols = len(board[0])
queue = []
steps = [(0,1),(0,-1),(1,0),(-1,0)]
for i in range(rows):
for j in range(cols):
if (i==0 or i==rows-1 or j==0 or j==cols-1) and board[i][j]=='O':
board[i][j]='#'
queue.append((i,j))
while queue:
x,y = queue.pop(0)
for step in steps:
x1 = x+step[0]
y1 = y+step[1]
if x1>=0 and x1<rows and y1>=0 and y1<cols and board[x1][y1]=='O':
board[x1][y1]='#'
queue.append((x1,y1))
for i in range(rows):
for j in range(cols):
if board[i][j]=='O':
board[i][j]='X'
elif board[i][j]=='#':
board[i][j]='O'
return
复杂度分析
时间复杂度:O(MN)
空间复杂度:广度优先搜索队列的开销
417. 太平洋大西洋水流问题
417. 太平洋大西洋水流问题
思路:
从边缘向中间;
分别计算太平洋和大西洋可达的单元;
求交集。
class Solution:
steps = [(0,1),(0,-1),(1,0),(-1,0)]
def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:
if not matrix or not matrix[0]:
return []
rows = len(matrix)
cols = len(matrix[0])
res1 = set()#太平洋
res2 = set()#大西洋
for i in range(rows):
self.dfs(matrix,res1,i,0)
self.dfs(matrix,res2,i,cols-1)
for j in range(cols):
self.dfs(matrix,res1,0,j)
self.dfs(matrix,res2,rows-1,j)
return res1&res2#set求交集
def dfs(self,matrix,res,i,j):
res.add((i,j))
for step in self.steps:
x = i+step[0]
y = j+step[1]
if x>=0 and x<len(matrix) and y>=0 and y<len(matrix[0]) \
and matrix[x][y]>=matrix[i][j] and (x,y) not in res:
self.dfs(matrix,res,x,y)