最近刷了一些图论层序遍历的题目,想做一个小小总结。
一般图论貌似都可以使用dfs或者bfs来做,我现在在专攻bfs这个模块。
一共刷了四道题:迷宫最近出口、最短的桥、最小基因变化、跳跃游戏
我认为前两题可以算是一个类型的题目,是根据当前位置四周(上下左右)的情况判断是否可以走、或者是否是岛屿来处理
迷宫入口最近出口的话,需要定义dx=[1,0,-1,0] dy=[0,1,0,-1]来提供一个单位矢量,我理解的思路是定义一个queue(用来存放要去的地方和走的路程)(like:queue=deque([(entrance[0],entrance[1],0)]))然后每走过一个地方都要把原来的地方定义为墙或者“-1”这样子防止再走回去。
然后路程就可以写为如下内容。
while queue:
x,y,num=queue.popleft()
for index in range(4):
nx=x+dx[index]
ny=y+dy[index]
if 0<=nx<m and 0<=ny<n and maze[nx][ny]=='.':
if nx==0 or nx==m-1 or ny==0 or ny==n-1:
return num
queue.append((nx,ny,num+1))
maze[nx][ny]='+'
return -1
首先把queue队列里面的前置内容提取出来,然后对其四周进行遍历,首先进行一个大的条件筛选(很重要!方便后续操作)把在矩阵范围内且路径为路的条件下处理,先定义一个if,在这个if下面再判断一下节点是否到达边界(到了就直接return),如果没到边界的话就把节点加入queue并且把节点设置为已到访。
最短的桥需要注意一个问题就是,题目说的岛屿只有两个,所以一触碰到岛屿就可以进行四周轮询。
这个题目的思路是两层for循环,第二层for循环处理具体岛屿节点,只要触碰到了岛屿就append进入island,然后在接下来去进行一个while True:循环(在和上述触碰于同一个for循环里面),while True:有一个条件是必须碰到另一个island才停下来,如果没碰到的话就把海洋(0)也添加进queue中(这个queue是while循环独有的,queue都是存放需要遍历的节点)然后step+=1
最小基因变化这道题主要是看对字符串的处理,拼接字符串的方法最建议使用切片(like:q=u[:i]+v+u[i+1:])
B=['A','C','G','T']
bank_set=set(bank)
queue=deque([start])
if start in bank_set:
bank_set.remove(start)
res=0
while queue:
for _ in range(len(queue)):
x=queue.popleft()
for index in range(len(x)):
for i in B:
nx=x[:index]+i+x[index+1:]
if nx==end:
return res
if nx in bank_set:
queue.append(nx)
bank_set.remove(nx)
res+=1
return False
最后一道题是跳跃游戏,我觉得跳跃游戏还是比较好整的,但是当时没想出来
跳跃游戏是这样的,给一个arr=[4,2,3,0,3,1,2],start=5 然后问每一次能跳到i+arr[i] i-arr[i]两个index,问能不能跳到0那里?
used=set()
while queue:
for _ in range(len(queue)):
i=queue.popleft()
for index in [i-arr[i],i+arr[i]]:
if 0<=index<n and index not in used:
if arr[index]==0:
return True
used.add(index)
queue.append(index)
return False
像这种最开始要for _ in range(len(queue)):的是可以保证把queue里面的内容先清一清,加上不会碍事(可以看到queue.popleft()就直接加上for这个语句?我瞎想的,后面再验证)