解题思路
plusOne和minusOne分别用于计算拨动一位之后的密码锁数字,单向bfs中每次取一组数字,初始为‘0000’,然后依次判断是否为deadend或target,都不是则依次进行向上或向下拨动1操作然后加入到待考察队列(q)以及出现过数字的队列(visited),判断结束之后操作步数+1
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
def plusOne(s, i):
s_list = list(s)
if s_list[i] == '9':
s_list[i] = '0'
else:
s_list[i] = str(int(s_list[i])+1)
return "".join(s_list)
def minusOne(s, i):
s_list = list(s)
if s_list[i] == '0':
s_list[i] = '9'
else:
s_list[i] = str(int(s_list[i])-1)
return "".join(s_list)
deads = set()
for i in deadends:
deads.add(i)
visited = set()
q = ['0000']
visited.add('0000')
depth = 0
while q:
for _ in range(len(q)):
cur = q.pop(0)
if cur in deads:
continue
if cur == target:
return depth
for j in range(4):
up = plusOne(cur, j)
if up not in visited:
q.append(up)
visited.add(up)
down = minusOne(cur, j)
if down not in visited:
q.append(down)
visited.add(down)
depth += 1
return -1
双向BFS优化:
用两个set记录开始和结束的密码锁数值,依次判断是否为deadend或target,然后用temp记录每次操作过程中产生的经过1位操作之后的密码锁数值,结束后操作步数+1,为了进行下次操作,将q2赋予q1,temp赋予q2
#BiBFSBiBFS
deads = set()
for i in deadends:
deads.add(i)
visited = set()
q1 = set()
q2 = set()
q1.add('0000')
q2.add(target)
depth = 0
while q1 and q2:
temp = set()
for cur in q1:
if cur in deads:
continue
if cur in q2:
return depth
visited.add(cur)
for j in range(4):
up = plusOne(cur, j)
if up not in visited:
temp.add(up)
down = minusOne(cur, j)
if down not in visited:
temp.add(down)
depth += 1
q1 = q2
q2 = temp
return -1