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。所有單詞具有相同的長度。所有單詞只由...