[LeetCode] Implement Magic Dictionary 實現神奇字典
Implement a magic directory with buildDict
, and search
methods.
For the method buildDict
, you'll be given a list of non-repetitive words to build a dictionary.
For the method search
, you'll be given a word, and judge whether if you modify exactly one character into another character in this word, the modified word is in the dictionary you just built.
Example 1:
Input: buildDict(["hello", "leetcode"]), Output: Null Input: search("hello"), Output: False Input: search("hhllo"), Output: True Input: search("hell"), Output: False Input: search("leetcoded"), Output: False
Note:
- You may assume that all the inputs are consist of lowercase letters
a-z
- For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest.
- Please remember to RESET your class variables declared in class MagicDictionary, as static/class variables are persisted across multiple test cases. Please see here for more details.
這道題讓我們設計一種神奇字典的資料結構,裡面有一些單詞,實現的功能是當我們搜尋一個單詞,只有存在和這個單詞只有一個位置上的字元不相同的才能返回true,否則就返回false,注意完全相同也是返回false,必須要有一個字元不同。博主首先想到了One Edit Distance那道題,只不過這道題的兩個單詞之間長度必須相等。所以只需檢測和要搜尋單詞長度一樣的單詞即可,所以我們用的資料結構就是根據單詞的長度來分,把長度相同相同的單詞放到一起,這樣就可以減少搜尋量。那麼對於和要搜尋單詞進行比較的單詞,由於已經保證了長度相等,我們直接進行逐個字元比較即可,用cnt表示不同字元的個數,初始化為0。如果當前遍歷到的字元相等,則continue;如果當前遍歷到的字元不相同,並且此時cnt已經為1了,則break,否則cnt就自增1。退出迴圈後,我們檢測是否所有字元都比較完了且cnt為1,是的話則返回true,否則就是跟下一個詞比較。如果所有詞都比較完了,則返回false,參見程式碼如下:
解法一:
class MagicDictionary { public: /** Initialize your data structure here. */ MagicDictionary() {} /** Build a dictionary through a list of words */ void buildDict(vector<string> dict) { for (string word : dict) { m[word.size()].push_back(word); } } /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ bool search(string word) { for (string str : m[word.size()]) { int cnt = 0, i = 0; for (; i < word.size(); ++i) { if (word[i] == str[i]) continue; if (word[i] != str[i] && cnt == 1) break; ++cnt; } if (i == word.size() && cnt == 1) return true; } return false; } private: unordered_map<int, vector<string>> m; };
下面這種解法實際上是用到了字首樹中的search的思路,但是我們又沒有整個用到prefix tree,博主感覺那樣寫法略複雜,其實我們只需要借鑑一下search方法就行了。我們首先將所有的單詞都放到一個集合中,然後在search函式中,我們遍歷要搜尋的單詞的每個字元,然後把每個字元都用a-z中的字元替換一下,形成一個新詞,當然遇到本身要跳過。然後在集合中看是否存在,存在的話就返回true。記得換完一圈字元後要換回去,不然就不滿足只改變一個字元的條件了,參見程式碼如下:
解法二:
class MagicDictionary { public: /** Initialize your data structure here. */ MagicDictionary() {} /** Build a dictionary through a list of words */ void buildDict(vector<string> dict) { for (string word : dict) s.insert(word); } /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ bool search(string word) { for (int i = 0; i < word.size(); ++i) { char t = word[i]; for (char c = 'a'; c <= 'z'; ++c) { if (c == t) continue; word[i] = c; if (s.count(word)) return true; } word[i] = t; } return false; } private: unordered_set<string> s; };
類似題目:
參考資料: