代码随想录算法训练营Day 61| 图论 part01 | 797.所有可能的路径、200.岛屿数量(深搜)(广搜)
文章目录
797.所有可能的路径
一、DFS
class Solution(object):
def allPathsSourceTarget(self, graph):
"""
:type graph: List[List[int]]
:rtype: List[List[int]]
"""
res = []
path = []
def dfs(x):
if x==len(graph)-1:
res.append(path[:])
return
for i in graph[x]:
path.append(i)
dfs(i)
path.pop()
path.append(0)
dfs(0)
return res
二、两种写法
邻接矩阵写法
def dfs(graph, x, n, path, result):
if x == n:
result.append(path.copy())
return
for i in range(1, n + 1):
if graph[x][i] == 1:
path.append(i)
dfs(graph, i, n, path, result)
path.pop() # 回溯,移除路径中的最后一个节点
def main():
import sys
input = sys.stdin.read
data = input().split()
index = 0
n = int(data[index])
index += 1
m = int(data[index])
index += 1
graph = [[0] * (n + 1) for _ in range(n + 1)]
for _ in range(m):
s = int(data[index])
index += 1
t = int(data[index])
index += 1
graph[s][t] = 1
result = []
path = [1]
dfs(graph, 1, n, path, result)
if len(result) == 0:
print(-1)
else:
for pa in result:
print(' '.join(map(str, pa)))
if __name__ == '__main__':
main()
邻接表写法
def dfs(graph, x, n, path, result):
if x == n:
result.append(path.copy())
return
for i in graph[x]:
path.append(i)
dfs(graph, i, n, path, result)
path.pop() # 回溯,移除路径中的最后一个节点
def main():
import sys
input = sys.stdin.read
data = input().split()
index = 0
n = int(data[index])
index += 1
m = int(data[index])
index += 1
graph = [[] for _ in range(n + 1)] # 邻接表实现
for _ in range(m):
s = int(data[index])
index += 1
t = int(data[index])
index += 1
graph[s].append(t) # 填充邻接表
result = []
path = [1] # 路径开始节点设为1
dfs(graph, 1, n, path, result) # 从节点1开始DFS
if not result:
print(-1)
else:
for pa in result:
print(' '.join(map(str, pa)))
if __name__ == '__main__':
main()
广度优先搜索理论基础
本题思路:遇到一个没有遍历过的节点陆地,计数器就加一,然后把该节点陆地所能遍历到的陆地都标记上。
再遇到标记过的陆地节点和海洋节点的时候直接跳过。 这样计数器就是最终岛屿的数量。
那么如果把节点陆地所能遍历到的陆地都标记上呢,就可以使用 DFS,BFS或者并查集。
一、示例
from collections import deque
dir = [(0, 1), (1, 0), (-1, 0), (0, -1)] # 创建方向元素
def bfs(grid, visited, x, y):
queue = deque() # 初始化队列
queue.append((x, y)) # 放入第一个元素/起点
visited[x][y] = True # 标记为访问过的节点
while queue: # 遍历队列里的元素
curx, cury = queue.popleft() # 取出第一个元素
for dx, dy in dir: # 遍历四个方向
nextx, nexty = curx + dx, cury + dy
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界了,直接跳过
continue
if not visited[nextx][nexty]: # 如果节点没被访问过
queue.append((nextx, nexty)) # 加入队列
visited[nextx][nexty] = True # 标记为访问过的节点
200.岛屿数量(深搜)
一、法一
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
m,n=len(grid),len(grid[0]) # row,col
# print(m,n)
visited = [[False]*n for _ in range(m)]
dirs = [(-1,0),(0,1),(1,0),(0,-1)]
result = 0
def dfs(x,y):
for d in dirs:
nextx = x+d[0]
nexty = y+d[1]
if nextx<0 or nextx>=m or nexty<0 or nexty>=n:
continue
if visited[nextx][nexty] ==False and grid[nextx][nexty]=='1':
visited[nextx][nexty]=True
dfs(nextx,nexty)
for i in range(m):
for j in range(n):
if not visited[i][j] and grid[i][j]=='1':
visited[i][j]=True
dfs(i,j)
result +=1
return result
二、法二
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
m,n=len(grid),len(grid[0]) # row,col
# print(m,n)
visited = [[False]*n for _ in range(m)]
dirs = [(-1,0),(0,1),(1,0),(0,-1)]
result = 0
# 法2
def dfs(x,y):
if visited[x][y] or grid[x][y]=='0':
return
visited[x][y]=True
for d in dirs:
nextx = x+d[0]
nexty = y+d[1]
if nextx<0 or nextx>=m or nexty<0 or nexty>=n:
continue
dfs(nextx,nexty)
for i in range(m):
for j in range(n):
if visited[i][j]==False and grid[i][j]=='1':
dfs(i,j)
result +=1
return result
三、本题总结
版本一的写法是 :下一个节点是否能合法已经判断完了,传进dfs函数的就是合法节点。
版本二的写法是:不管节点是否合法,上来就dfs,然后在终止条件的地方进行判断,不合法再return。
200.岛屿数量(广搜)
一、法一
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
m,n=len(grid),len(grid[0]) # row,col
# print(m,n)
visited = [[False]*n for _ in range(m)]
dirs = [(-1,0),(0,1),(1,0),(0,-1)]
result = 0
def bfs(i,j):
q = collections.deque()
q.append((i,j))
visited[i][j]=True
while q:
x,y = q.popleft()
for d in dirs:
nextx = x+d[0]
nexty = y+d[1]
if nextx<0 or nextx>=m or nexty<0 or nexty>=n:
continue
if visited[nextx][nexty] or grid[nextx][nexty]=='0':
continue
q.append((nextx,nexty))
visited[nextx][nexty]=True
for i in range(m):
for j in range(n):
if not visited[i][j] and grid[i][j]=='1':
result +=1
bfs(i,j)
return result