深度优先搜索(DFS)类似于树的先序遍历,虽然是针对图的,但是只要在二叉树、图上都可以使用深度优先搜索的思维。
深度优先搜索的过程:
- 访问第一个节点,将该节点的状态设置为已访问(因为图可能有环,最后会再次搜索到该节点)
- 找到第一个节点的第一个未被访问的邻接节点(这种寻找方式有很多种,根据实际存储结构的不同有不同的处理方式),以该节点为新顶点,重复向下查找新的未被访问的邻接节点,直到当前访问的节点没有邻接节点
- 查找上一个未被访问过的且仍有未被访问的邻接点的顶点,并访问它的未被访问的其他节点
- 重复2、3,直到所有点都被访问
伪代码:
visited=[]
#x是当前访问的节点,visited是用来存储已访问的节点
def DFS(x):
print(x.val)
visited.append(x)
#在这个位置访问x的所有邻接节点
#如果该节点也没有被访问,就以他为顶点继续找邻接节点
for i in (x的所有邻接节点):
if i not in visited:
DFS(i)
应用:
解法:该题使用visited标记节点是否被访问过。1.若该节点没有被访问过,则对该节点使用深度优先搜索,并使省份数量加一 2.在深度优先搜索中,每访问一个节点,就把它加入到visited中去 3.这样最后深度优先搜索的次数就是省份的数量
注意:该题dfs中的for循环就对饮伪代码中的for循环找所有邻接点
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
def dfs(i: int):
for j in range(provinces):
if isConnected[i][j] == 1 and j not in visited:
visited.add(j)
dfs(j)
provinces = len(isConnected)
visited = set()
circles = 0
for i in range(provinces):
if i not in visited:
dfs(i)
circles += 1
return circles
解法:本质还是使用深度优先搜索,看哪一条深度优先搜索的路径先达到终点。需要注意的,在该解法中,使用队列(实际上用列表实现)queue来存储队列中的节点和到该节点需要使用的步数(step)。
注意:while queue下的for循环就对应伪代码中的查找邻接节点。所以不同的存储方式有不同的处理方法
class Solution:
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
n=len(grid)
if grid[0][0]==1 or grid[n-1][n-1]==1:
return -1
if n<=2:
return n
queue=[(0,0,1)]
grid[0][0]=1
t=[]
while queue:
i,j,step=queue.pop(0)
for x,y in [(-1,-1), (1,0), (0,1), (-1,0), (0,-1), (1,1), (1,-1), (-1,1)]:
if i+x==n-1 and j+y==n-1:
return step+1
if n>i+x>=0 and n>j+y>=0 and grid[i+x][j+y]==0:
queue.append((i+x,j+y,step+1))
grid[i+x][j+y]=1
return -1