leetcode 752 開啟轉盤鎖

2021-10-08 14:09:02 字數 3585 閱讀 8775

752. 開啟轉盤鎖

你有乙個帶有四個圓形撥輪的轉盤鎖。每個撥輪都有10個數字: 『0』, 『1』, 『2』, 『3』, 『4』, 『5』, 『6』, 『7』, 『8』, 『9』 。每個撥輪可以自由旋**例如把 『9』 變為 『0』,『0』 變為 『9』 。每次旋轉都只能旋轉乙個撥輪的一位數字。

鎖的初始數字為 『0000』 ,乙個代表四個撥輪的數字的字串。

列表 deadends 包含了一組死亡數字,一旦撥輪的數字和列表裡的任何乙個元素相同,這個鎖將會被永久鎖定,無法再被旋轉。

字串 target 代表可以解鎖的數字,你需要給出最小的旋轉次數,如果無論如何不能解鎖,返回 -1。

示例 1:

輸入:deadends = [「0201」,「0101」,「0102」,「1212」,「2002」], target = 「0202」

輸出:6

解釋:可能的移動序列為 「0000」 -> 「1000」 -> 「1100」 -> 「1200」 -> 「1201」 -> 「1202」 -> 「0202」。

注意 「0000」 -> 「0001」 -> 「0002」 -> 「0102」 -> 「0202」 這樣的序列是不能解鎖的,

因為當撥動到 「0102」 時這個鎖就會被鎖定。

示例 2:

輸入: deadends = [「8888」], target = 「0009」

輸出:1

解釋:把最後一位反向旋轉一次即可 「0000」 -> 「0009」。

示例 3:

輸入: deadends = [「8887」,「8889」,「8878」,「8898」,「8788」,「8988」,「7888」,「9888」], target = 「8888」

輸出:-1

解釋:無法旋轉到目標數字且不被鎖定。

示例 4:

輸入: deadends = [「0000」], target = 「8888」

輸出:-1

鎖盤有四個鍵,每乙個鍵每一有兩種變換的可能,所以個原始輸入進去,會產生8個後續的變化可能。

但是我們有乙個死區dead,和乙個走過的數字visited。這兩類內的數字就不能在實際產生並且加入到queue佇列中。

下面是一種單向的bfs方法求解的過程:

class

solution

:def

openlock

(self, deadends: list[

str]

, target:

str)

->

int:

if'0000'

in deadends:

return-1

queue = collections.deque(

)'0000'

)#加入佇列

visited =

set(

)#建立乙個集合,儲存走過的路,防止往回走

step =

1while queue:

for i in

range

(len

(queue)):

#每次需要迴圈多少次

cur = queue.popleft(

)for j in

range(4

):#由於有四個滑動鍵,每乙個有兩種變換(加減)

for k in[-

1,1]

: tempcur = cur[

:j]+

str(

(int

(cur[j]

)+k+10)

%10)+ cur[j+1:

]if tempcur not

in deadends:

if tempcur == target:

return step

if tempcur not

in visited:

#沒有走過,加入到佇列

visited.add(tempcur)

#加入走過的集合

step +=

1return

-1

這裡我們還考慮是否能使用雙向的bfs,因為雙向的bfs的使用條件是,我們必須直到起始點和終點。有了這兩個點的資訊,我們才能夠雙向的往中間靠,減少複雜度和計算時間。

雙向bfs和單向bfs在程式上的區別就是,雙向的bfs,我們設定的資料型別是list, list也可以左右pop。

其次,最重要的是:我們在每次遍歷bfs的時候,我們都是遍歷的queue, 每次結束遍歷的的時候,我們queue2 - > queue,把目標列表賦值給起始列表,其實列表的下一批結果賦值給目標列表。

這樣做的目的就是,單次交叉bfs,減少中間過程產生的結果。並且每次都只迴圈乙個列表,減少了程式的複雜度。

class

solution

:def

openlock

(self, deadends: list[

str]

, target:

str)

->

int:

if'0000'

in deadends:

return-1

queue =

'0000'

)#加入佇列

deadends =

set(deadends)

queue2 =

[target]

visited =

set(

)#建立乙個集合,儲存走過的路,防止往回走

visited.add(

'0000'

) step =

1while queue and queue2:

qlen =

len(queue)

tempset =

#設定本次queue的下一批可能節點,最後賦值給queue2,交叉bfs

for i in

range

(qlen)

:#每次需要迴圈多少次

cur = queue.pop(0)

for j in

range(4

):for k in[-

1,1]

: tempcur = cur[

:j]+

str(

(int

(cur[j]

)+k+10)

%10)+ cur[j+1:

]if tempcur not

in deadends:

if tempcur in queue2:

return step

if tempcur not

in visited:

#沒有走過,加入到佇列

visited.add(tempcur)

#加入走過的集合

step +=

1 queue = queue2#目標值queue2列表賦值給queue

queue2 = tempset#本次queue的下一批節點賦值給queue2

return

-1

開啟轉盤鎖(LeetCode 752)

你有乙個帶有四個圓形撥輪的轉盤鎖。每個撥輪都有10個數字 0 1 2 3 4 5 6 7 8 9 每個撥輪可以自由旋 例如把 9 變為 0 0 變為 9 每次旋轉都只能旋轉乙個撥輪的一位數字。鎖的初始數字為 0000 乙個代表四個撥輪的數字的字串。列表 deadends 包含了一組死亡數字,一旦撥輪...

leetcode 752 開啟轉盤鎖

目錄你的鼓勵也是我創作的動力 你有乙個帶有四個圓形撥輪的轉盤鎖。每個撥輪都有10個數字 0 1 2 3 4 5 6 7 8 9 每個撥輪可以自由旋 例如把 9 變為 0 0 變為 9 每次旋轉都只能旋轉乙個撥輪的一位數字。鎖的初始數字為 0000 乙個代表四個撥輪的數字的字串。列表 deadends...

leetcode752 開啟轉盤鎖

我們可以將 0000 到 9999 這 10000 狀態看成圖上的 10000 個節點,兩個節點之間存在一條邊,當且僅當這兩個節點對應的狀態只有 1 位不同,且不同的那位相差 1 包括 0 和 9 也相差 1 的情況 並且這兩個節點均不在陣列 deadends 中。那麼最終的答案即為 0000 到 ...