文章目录
1. leetcode208-实现 Trie (前缀树)
题目:https://leetcode-cn.com/problems/implement-trie-prefix-tree/
class Trie {
public:
bool isEnd=false;
Trie* next[26] = {nullptr};
Trie() {
}
void insert(string word) {
Trie* root = this;
for(char c:word)
{
if(root->next[c-'a']==nullptr) root->next[c-'a']=new Trie();
root = root->next[c-'a'];
}
root->isEnd = true;
}
bool search(string word) {
Trie* root = this;
for(char c:word)
{
if(root->next[c-'a']==nullptr) return false;
root = root->next[c-'a'];
}
return root->isEnd;
}
bool startsWith(string prefix) {
Trie* root = this;
for(char c:prefix)
{
if(root->next[c-'a']==nullptr) return false;
root = root->next[c-'a'];
}
return true;
}
};
2. leetcode211-添加与搜索单词-数据结构设计
题目:https://leetcode-cn.com/problems/design-add-and-search-words-data-structure/
分析:与 leetcode208 的区别在于本题中搜索的单词是模糊匹配。而深度优先遍历搜索是一种不断试探的方案。
class WordDictionary {
public:
class Node{
public:
bool isEnd=false;
Node* next[26]={nullptr};
} *node;
WordDictionary() {
node = new Node();
}
void addWord(string word) {
auto root = node;
for(auto& c:word)
{
int u=c-'a';
if(!root->next[u]) root->next[u]=new Node();
root = root->next[u];
}
root->isEnd=true;
}
//因为string word没有使用引用形式,所以多占用了很多内存,也占用了很多时长拷贝字符串
bool DFS_Search(int i, string& word, Node* pnode)
{
if(i==word.length()) return pnode->isEnd;
if(word[i]!='.')
{
int u=word[i]-'a';
if(!pnode->next[u]) return false;
return DFS_Search(i+1,word,pnode->next[u]);
}
else
{
for(int j=0; j<26; ++j)
{
if(pnode->next[j] && DFS_Search(i+1, word, pnode->next[j]))
return true;
}
return false;
}
}
bool search(string word) {
return DFS_Search(0, word, node);
}
};
3. leetcode648-单词替换
题目:https://leetcode-cn.com/problems/replace-words/
分析:字典树+string分割
class Solution {
public:
class Trie{
public:
bool isEnd=false;
Trie* next[26]={nullptr};
void insert(string& str)
{
Trie* root = this;
for(char c:str)
{
if(root->next[c-'a']==nullptr)
root->next[c-'a']=new Trie();
root = root->next[c-'a'];
}
root->isEnd = true;
}
string replace(string& str)
{
Trie* root = this;
string ans;
for(char c:str)
{
if(root->next[c-'a']==nullptr) return str;
ans += c;
if(root->next[c-'a']->isEnd) break;
root = root->next[c-'a'];
}
return ans;
}
};
string replaceWords(vector<string>& dictionary, string sentence) {
Trie t;
for(string str:dictionary)
t.insert(str);
string res, s;
istringstream iss(sentence);
while(iss>>s)
{
res += t.replace(s);
res += ' ';
}
res.pop_back();
return res;
}
};
4. leetcode14-最长公共前缀
题目:https://leetcode-cn.com/problems/longest-common-prefix/
分析:首先创建字典树,将第一个字符串读入字典树,此时公共前缀即为第一个字符串。接下来的字符串们,如果有某个字符在字典树中不存在,就可以停止该字符串的遍历,公共前缀变短;当然也会存在字符串提前结束的情况,此时公共前缀也会变短;如果遍历某字符串时发现当前字典树的 isEnd 为 true,也直接退出循环,此时公共前缀不变。我们用字典树的 isEnd 标识,记录当前字典树的公共前缀。所以要记得在退出循环时,要对 isEnd 置位。
class Solution {
public:
class Trie{
public:
Trie* next[26]={nullptr};
bool isEnd = false;
int count = 0;
void insert(string& str, string& common)
{
Trie* root = this;
common.clear();
for(const auto& c:str)
{
if(root->next[c-'a']==nullptr)
{
if(count==0)
root->next[c-'a'] = new Trie();
else break;
}
if(root->isEnd) break;
root = root->next[c-'a'];
common += c;
}
root->isEnd = true;//这句话不能忘记
++count;
}
};
string longestCommonPrefix(vector<string>& strs) {
Trie t;
string res;
for(auto& str:strs)
t.insert(str,res);
return res;
}
};