題目描述:
給定乙個單詞集合dict,其中每個單詞的長度都相同。現從此單詞集合dict中抽取兩個單詞a、b。希望通過若干次操作把單詞a變成單詞b,每次操作可以改變單詞的乙個字母,同時,每次操作後,新產生的單詞必須是在給定的單詞集合dict中。求所有行得通步數最少的修改方法。
舉個例子如下:
given:
a ="hit"
b ="cog"
dict =["hit","hot","dot","dog","lot","log","cog"]
return
[["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]即把字串a ="hit"轉變成字串b = "cog",有以下兩種可能:
"hit"-> "hot" -> "dot" -> "dog"-> "cog";
"hit"-> "hot" -> "lot" -> "log" ->"cog"。
分析:這個題目本質上是圖的最短路徑問題,此題看似跟字串編輯距離相似,但其實區別特別大,原因是最短編輯距離是讓某個單詞增加乙個字元或減少乙個字元或修改乙個字元達到目標單詞,來求變換的最少次數,但此最小運算元問題就只是改變乙個字元。
這個題目的關鍵就是如何根據詞典dict建立圖,這麼幾個問題要思考,節點是什麼?邊如何建立?圖是有方向的還是無方向的?
對於本題,我們的圖的節點就是字典裡的單詞,兩個節點有連邊,對應著我們可以把乙個單詞按照規則變為另外乙個單詞。比如我們有單詞hat,它應該與單詞cat有一條連邊,因為我們可以把h變為c,反過來我們也可以把c變為h,所以我們建立的連邊應該是無向的。
如何建圖?有兩種辦法:
1:我們可以把字典裡的任意兩個單詞,通過迴圈判斷一下這兩個單詞是否只有乙個位置上的字母不同。即假設字典裡有n個單詞,我們遍歷任意兩個單詞 的複雜度是o( ),如果每個單詞長度為length,我們判斷兩個單詞是否連邊的複雜度是o(length),所以這個建圖的總複雜度是 o(
*length)。但當n比較大時,這個複雜度非常高。
2:把字典裡地每個單詞的每個位置的字母修改一下,從字典裡查詢一下,看修改後的單詞是否在字典裡出現過。若用基於red-black tree的map查詢,其查詢複雜度為o(logn),若用基於hashmap的unordered_map,則查詢複雜度為o(1)。即我們需要遍歷字典裡地每乙個單詞o(n),嘗試修改每個位置的每個字母,對每個位置我們需要嘗試26個字母(其實是
25個,因為要改得和原來不同),因此這部分複雜度是o(26*length),總複雜度是o(26 * n * length)。
上面兩種方法孰優孰劣呢?直接比較 *length 與 26 * n * length的大小。很明顯,通常情況下,字典裡的單詞個數非常多,也就是n比較大,因此第二種方法效果會好一些。
建立好圖之後,這個問題就轉化為了最短路徑的問題,不再贅述。下圖是給定例子的圖示:
最小運算元
剛才在剛果準備挑戰最小運算元的。可是操作失誤,調教了白 在自己電腦上用c 環境試了試。竟然花了3個小時,哎,挑戰也是失敗了。題目詳情 給了a b兩個單詞和乙個單詞集合dict,每個的長度都相同。我們希望通過若干次操作把單詞a變成單詞b,每次操作可以改變單詞中的乙個字母,同時,新產生的單詞必須是在給定...
最小運算元
給了a b兩個單詞和乙個單詞集合dict,每個的長度都相同。我們希望通過若干次操作把單詞a變成單詞b,每次操作可以改變單詞中的乙個字母,同時,新產生的單詞必須是在給定的單詞集合dict中。求所有行得通步數最少的修改方法。舉個例子如下 given a hit b cog dict hot dot do...
最小運算元遞迴實現
題目 給了a b兩個單詞和乙個單詞集合dict,每個的長度都相同。我們希望通過若干次操作把單詞a變成單詞b,每次操作可以改變單詞中的乙個字母,同時,新產生的單詞必須是在給定的單詞集合dict中。求所有行得通步數最少的修改方法。舉個例子如下 given a hit b cog dict hot dot...