defchildren(status): ... defsolution(): start = ... end = ... queue = [(start,0)] #队列:记录节点数据,也记录了节点所在深度 marked = set() #标记字典:用于排除重复 marked.add(start) while queue: s,r = queue.pop(0) #if s == end: #当到达末尾时,此时的深度就是最短路径 # return r for ss in children(s): if ss == end: #优化:可以将判断放在循环中,这样可以少一轮子节点的遍历,但是注意要对结果加1 return r + 1 ifnot ss in marked: queue.append((ss,r + 1)) marked.add(ss) return -1#无路径可达,返回-1
defchildren(status): ... defbfs(queue,marked,targeted): while queue: s,r = queue.pop(0) #if s in targeted: # return r + targeted[s] #双向遍历,当节点在2个队列中都存在时,要累加该节点在2个队列中的深度 for ss in children(s): if ss in targeted: #优化:可以将判断放在循环中,这样可以少一轮子节点的遍历,但是注意要对结果加1 return r + 1 + targeted[ss] ifnot ss in marked: queue.append((ss,r + 1)) marked[ss] = r + 1 return -1 defsolution(): start= ... end= ... q1=[(start,0)] #队列1,从开始节点遍历 q2=[(end,0)] #队列2,从结束节点遍历 m1={start:0} #队列1的标记字典,除了标记,还要记录节点深度,用于最后重合时,将2个节点深度累加 m2={end:0} #队列2的标记字典 while q1 and q2: #2个队列都不能为空,其中一个为空,说明永不可能相交 t=-1 iflen(q1)>len(q2): #搜索较短的队列 t=bfs(q2,m2,m1) else: t=bfs(q1,m1,m2) if t>=0: return t #一旦搜索到结果,立即返回,否则继续循环。下次循环中2个队列长度发生变化,依然搜索较短的那个 return -1
classSolution: defslidingPuzzle(self, board: List[List[int]]) -> int: defchildren(status): ... 略 defbfs(queue,marked,targeted): while queue: s,r=queue.pop(0) if s in targeted: return r+targeted[s] for ss in children(s): ifnot ss in marked: queue.append((ss,r+1)) marked[ss]=r+1 return -1 start=tuple(board[0]+board[1]) end=(1,2,3,4,5,0) q1=[(start,0)] q2=[(end,0)] m1={start:0} m2={end:0} while q1 and q2: t=-1 iflen(q1)>len(q2): t=bfs(q2,m2,m1) else: t=bfs(q1,m1,m2) if t>=0: return t return -1
classSolution: defopenLock(self, deadends: List[str], target: str) -> int: deadends=set(deadends) if'0000'in deadends or target in deadends: return -1 defchildren(s): for i inrange(4): #四个拨轮轮流拨动一次能得到的结果 yield s[:i]+ str((int(s[i])+11)%10) +s[i+1:] #向上拨动一格 +1,加10再模10,循环拨动并防止数组越界 yield s[:i]+ str((int(s[i])+9)%10) +s[i+1:] #向下拨动一格 -1,加10再模10,循环拨动并防止数组越界 defbfs(queue,marked,targeted): while queue: s,r=queue.pop(0) if s in targeted: return r+targeted[s] for ss in children(s): ifnot ss in marked andnot ss in deadends: queue.append((ss,r+1)) marked[ss]=r+1 return -1 q1=[('0000',0)] q2=[(target,0)] m1={'0000':0} m2={target:0} while q1 and q2: t=-1 iflen(q1)>len(q2): t=bfs(q2,m2,m1) else: t=bfs(q1,m1,m2) if t>=0: return t return -1
defsnakesAndLadders(self, board: List[List[int]]) -> int: n=len(board) o=(n-1)%2 dic={} for i inrange(n-1,-1,-1): for j inrange(n): x=(n-i-1)*n + (j+1if i%2==o else n-j) if board[i][j]!=-1: dic[x]=board[i][j] defchildren(x): for i inrange(x+1,min(x+7,end+1)): if i in dic: yield dic[i] else: yield i start=1 end=n*n queue=[(start,0)] marked=set() marked.add(start) while queue: s,r=queue.pop(0) for ss in children(s): if ss == end: return r+1 ifnot ss in marked: queue.append((ss,r+1)) marked.add(ss) return -1
defladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: words=set(wordList) ifnot endWord in words: return0 defchildren(word): for i inrange(len(word)): for c inrange(26): s=word[:i]+chr(97+c)+word[i+1:] if s!=word and s in words: yield s queue=[(beginWord,1)] marked=set() marked.add(beginWord) while queue: s,r=queue.pop(0) for ss in children(s): if ss==endWord: return r+1 ifnot ss in marked: queue.append((ss,r+1)) marked.add(ss) return0
defcanCross(self, stones: List[int]) -> bool: dic=set(stones) defchildren(status): s,k=status for k inrange(status[1]-1,status[1]+2): if status[0]+k in dic: yield (status[0]+k,k) start=(0,0) end=stones[-1] queue=[start] marked=set() marked.add(start) while queue: s=queue.pop(0) for ss in children(s): if ss[0]==end: returnTrue ifnot ss in marked: queue.append(ss) marked.add(ss) returnFalse
defnumBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int: if source==target: return0 dic={} for i inrange(len(routes)): for j in routes[i]: ifnot j in dic: dic[j]=[] dic[j].append(i) defchildren(status): yieldfrom routes[status] queue=[] marked=set() for i in dic[source]: queue.append((i,0)) marked.add(i) while queue: s,r=queue.pop(0) for station in children(s): if station==target: return r+1 for bus in dic[station]: ifnot bus in marked: queue.append((bus,r+1)) marked.add(bus) return -1