leetcode-211. 新增與搜尋單詞 - 資料結構設計
阿新 • • 發佈:2021-10-20
leetcode-211. 新增與搜尋單詞 - 資料結構設計
題目:
請你設計一個數據結構,支援 新增新單詞 和 查詢字串是否與任何先前新增的字串匹配 。
實現詞典類 WordDictionary :
- WordDictionary() 初始化詞典物件
- void addWord(word) 將 word 新增到資料結構中,之後可以對它進行匹配
- bool search(word) 如果資料結構中存在字串與 word 匹配,則返回 true ;否則,返回 false 。word 中可能包含一些 '.' ,每個 . 都可以表示任何一個字母。
思路:
-
本題直接將所有的單詞存入陣列中,在查詢時遍歷所有單詞,但這樣程式碼查詢效率低下,可能會超時,因此我們可以對單詞根據程式碼根據長度進行分類,儲存到map<int,vector<string>>的資料結構中,map的key為長度,value為對應長度的單詞,插入單詞時先計算單詞長度再插入對應的陣列中,查詢時,直接根據單詞長度找到對應的集合,遍歷集合中的所有單詞,再進行逐字元匹配,如果是'.'則跳過該次,如果有單詞匹配成功則返回true。
-
本題也可以通過字首樹解決,因為單詞只有26個,因此構建的字典樹為26叉樹,並置一個標誌isEnd記錄此字母是否為單詞末尾
資料結構:
class TrieNode{ public: //儲存孩子節點 vector<TrieNode*> child; //末尾標誌 bool isEnd; TrieNode(){ //初始化孩子節點 child=vector<TrieNode*>{26,nullptr}; //預設置為false,插入時將最後一個字母的標誌置為true isEnd=false; }; };
插入元素時,通過遍歷將單詞合併到字首樹
查詢元素時,
- 如果遍歷到單詞末尾,則意味著單詞匹配成功,返回true
- 如果單當前字母為a-z,則遞迴判斷trie->child[word[i]-'a']和word[i+1:]的查詢結果
- 如果遍歷的當前字母為'.',則需要對每個子節點都進行一次遞迴查詢
Code
- map集合
class WordDictionary { public: map<int,vector<string>> m; WordDictionary() { } void addWord(string word) { if(m.count(word.size())==0){ vector<string> cur={word}; m[word.size()]=cur; } else{ m[word.size()].push_back(word); } } bool search(string word) { int len=word.size(); if(m.count(len)==0){ return false; } for(auto item:m[word.size()]){ bool have=true; for(int i=0;i<len;i++){ if(word[i]!='.' && word[i]!=item[i]){ have=false; } } if(have){ return true; } } return false; } };
- 字首樹
class TrieNode{
public:
vector<TrieNode*> child;
bool isEnd;
TrieNode(){
child=vector<TrieNode*>{26,nullptr};
isEnd=false;
};
};
class WordDictionary {
public:
TrieNode* root;
WordDictionary() {
root=new TrieNode();
}
void addWord(string word) {
TrieNode* cur=root;
for(int i=0;i<word.size();i++){
if(cur->child[word[i]-'a']==nullptr){
cur->child[word[i]-'a']=new TrieNode();
}
cur=cur->child[word[i]-'a'];
}
//末尾標誌置位true
cur->isEnd=true;
};
bool search(string word) {
TrieNode* cur=root;
//遞迴查詢
return dfs(cur,0,word);
};
bool dfs(TrieNode* root,int inx,string word){
//查詢到末尾
if(inx==word.size()){
return root->isEnd;
};
//遇到'.'需要將26個字母都遍歷一次
if(word[inx]=='.'){
for(int i=0;i<26;i++){
if(root->child[i]!=nullptr && dfs(root->child[i],inx+1,word)){
return true;
}
}
return false;
}
else{
if(root->child[word[inx]-'a']!=nullptr && dfs(root->child[word[inx]-'a'],inx+1,word)){
return true;
}
return false;
};
};
};