leetcode 127 單詞接龍

2021-10-08 05:40:21 字數 4074 閱讀 9846

127. 單詞接龍

給定兩個單詞(beginword 和 endword)和乙個字典,找到從 beginword 到 endword 的最短轉換序列的長度。轉換需遵循如下規則:

每次轉換只能改變乙個字母。

轉換過程中的中間單詞必須是字典中的單詞。

說明:如果不存在這樣的轉換序列,返回 0。

所有單詞具有相同的長度。

所有單詞只由小寫字母組成。

字典中不存在重複的單詞。

你可以假設 beginword 和 endword 是非空的,且二者不相同。

示例 1:

輸入:beginword = 「hit」,

endword = 「cog」,

wordlist = [「hot」,「dot」,「dog」,「lot」,「log」,「cog」]

輸出: 5

解釋: 乙個最短轉換序列是 「hit」 -> 「hot」 -> 「dot」 -> 「dog」 -> 「cog」,

返回它的長度 5。

示例 2:

輸入:beginword = 「hit」

endword = 「cog」

wordlist = [「hot」,「dot」,「dog」,「lot」,「log」]

輸出: 0

解釋: endword 「cog」 不在字典中,所以無法進行轉換。

其實就是將beginword 單詞作為樹的根節點,依次向下遍歷,看這棵樹的葉子結點有沒有endword (有時候也不一定是葉子結點)。如果存在,返回其深度depth,反之返回0。此處有一點需要注意:

在樹上層出現過的字串沒必要在下層再次出現,因為如果該字串是轉換過程中必須經過的中間字串,那麼應該挑選上層的該字串繼續進行變化,它的轉換次數少。

因為題目所求的是最短轉換序列的長度,所以一定要記住這一點。

另外還有一點就是這個轉換規則:每次轉換只能改變乙個字母。每一次迭代中如何來找當前單詞的轉換單詞呢?這裡面所用的方法有很多種,我看了網上的一些帖子,大致分為兩種。一種是將改變的字母按照小寫字母排列情況分為26種情況,依次填進去進行判斷。另一種是將改變字母的那個位置用「_」代替,比如「hit」要改變第二個位置的字母,則可表示為「h_t」,而「hot」改變第二個位置的字母後也可表示為「h_t」,說明這兩個單詞是可以直接轉換的。

第一次嘗試做一下,結果倒是正確,就是最後提交的時候結果超出了時間限制,那個測試例子是真的長 ∩=∩ ,還能怎麼辦,改唄。

class

solution

:def

ladderlength

(self, beginword:

str, endword:

str, wordlist: list[

str])-

>

int:

num =

len(beginword)

queue = collections.deque(

) used =

defis_valid

(word, pattern)

:#判斷待加入的單詞是否符合加入條件:兩者不等,只有乙個字元不同

count =

0if word == pattern and word != endword:

return

false

for i in

range

(num)

:if word[i]

== pattern[i]

: count +=

1if count >= num -1:

return

true

else

:return

false

defsolve

( beginword, endword, wordlist)

:#bfs,每一將符合條件的字元加入佇列

cnt =

1while queue:

for _ in

range

(len

(queue)):

#本次佇列有多少數,就迴圈多少次

node = queue.popleft(

)#設定乙個使用過的列表記錄

for item in wordlist:

if is_valid(node, item)

and item not

in used and item not

in queue:

if item == endword:

return cnt+

1# print(queue)

cnt +=

1return

0return solve(beginword, endword, wordlist)

後來看了下題解,主要有兩種方法解決超時問題

我們在單詞匹配是否只差乙個字母的時候用了太多的計算時間, dog, cog,只有中間一位不同,我們可以建立乙個字典,其中 *og可以表示後兩位位og的三位單詞,這樣做的話,以來就建立了乙個字典,如果右只差一位的單詞,就會被聚合到乙個字典的鍵值下面。在進行bfs查詢匹配的時候,我們的效率會加快很多

還有一種方法就是雙向bfs,不止是單向從 begin 到 end, 我們也從 end 查詢 begin,這個方法但是我現在還沒仔細看,等下次回過頭再看。

class

solution

:def

ladderlength

(self, beginword:

str, endword:

str, wordlist: list[

str])-

>

int:

# bfs

from collections import deque, defaultdict

# 先驗判斷

if endword not

in wordlist:

return

0# 提前構建鄰接表 -> 用generic state做key

intermidiatewords = defaultdict(

list

) wordlen =

len(beginword)

for word in wordlist:

for i in

range

(wordlen)

: intermidiatewords[word[

:i]+

'*'+ word[i+1:

]]# 建佇列 加初始狀態

queue = deque(

) memo =

set(

) memo.add(beginword)

step =

1while queue:

size =

len(queue)

for _ in

range

(size)

: curword = queue.popleft(

)for i in

range

(wordlen)

: intermidiatecurword = curword[

:i]+

'*'+ curword[i+1:

]# 下乙個狀態的所有word

for word in intermidiatewords[intermidiatecurword]

:if word == endword:

return step +

1if word not

in memo:

memo.add(word)

step +=

1else

:return

0

LeetCode 127 單詞接龍

解題思路 1 這道題要找乙個最短路徑,可以聯想到圖的相關演算法 雖然我當時沒想到 那麼是不是應該使用最短路徑的相關演算法呢。其實不用 因為這個圖里每條邊的長度都是1,用乙個廣度優先演算法就搞定了。2規模的問題,如果你遍歷list裡的每個單詞的話,你會發現一直超時,因為有的list的規模給到了上千,每...

Leetcode 127單詞接龍

給定兩個單詞 beginword 和 endword 和乙個字典,找到從 beginword 到 endword 的最短轉換序列的長度。轉換需遵循如下規則 每次轉換只能改變乙個字母。轉換過程中的中間單詞必須是字典中的單詞。說明 示例 1 輸入 beginword hit endword cog wo...

Leetcode 127 單詞接龍

給定兩個單詞 beginword 和 endword 和乙個字典,找到從 beginword 到 endword 的最短轉換序列的長度。轉換需遵循如下規則 每次轉換只能改變乙個字母。轉換過程中的中間單詞必須是字典中的單詞。說明 如果不存在這樣的轉換序列,返回 0。所有單詞具有相同的長度。所有單詞只由...