题目描述
图论BFS模板
if target == "0000":
return 0
def get(status:str)->Generator[str, None, None]:
s = list(status)
for i in range(4):
num = s[i]
s[i] = num_prev(num)
yield "".join(s)
s[i] = num_next(num)
yield "".join(s)
s[i] = num
q = [AStar("0000", target, 0)]
seen = {"0000"}
while q:
node = heappop(q)
for next_status in get(node.status):
if next_status not in seen and next_status not in dead:
if target==next_status:
return node.g + 1
heapq.heappush(q, AStar(next_status, target, node.g + 1))
seen.add(next_status)
return -1
说明:
- 队列可以使用deque 或者优先队列 heapq 模块
- 需要一个seen 字典(查找时间复杂度较小)记录走过的状态
- 把状态和步数(status , step)打包成整体放入队列
- get函数是一个生成器,Generator[str, None, None] 三个参数分别表示 yieldtype, sendtype, returntype
题目分析
本题可以采用BFS模板
也可采用A*算法,采用启发式距离
参考:AStar算法应用
python实现
class AStar:
@staticmethod
def getH(status:str, target:str):
ret = 0
for i in range(4):
dist = abs(int(status[i]) - int(target[i]))
ret += min(dist, 10-dist)
return ret
def __init__(self, status:str, target:str, g:str)->None:
self.g = g
self.status = status
self.h = AStar.getH(status,target)
self.f = self.g + self.h
def __lt__(self, other:"AStar")->bool:
return self.f <other.f
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
if target == "0000":
return 0
dead = set(deadends)
if "0000" in dead:
return -1
def num_prev(x:str)->str:
return '9' if x=='0' else str(int(x)-1)
def num_next(x:str)->str:
return '0' if x=='9' else str(int(x)+1)
def get(status:str)->Generator[str, None, None]:
s = list(status)
for i in range(4):
num = s[i]
s[i] = num_prev(num)
yield "".join(s)
s[i] = num_next(num)
yield "".join(s)
s[i] = num
q = [AStar("0000", target, 0)]
seen = {"0000"}
while q:
node = heappop(q)
for next_status in get(node.status):
if next_status not in seen and next_status not in dead:
if target==next_status:
return node.g + 1
heapq.heappush(q, AStar(next_status, target, node.g + 1))
seen.add(next_status)
return -1