总结leetcode75中的前缀树算法题解题思路。
上一篇:力扣75——位运算
1 实现 Trie (前缀树)
题目:
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
请你实现 Trie 类:
Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
题解:
前缀树。对于每个类对象trie,它有一个长度为26的vector<Trie*>,记录着当前节点之后是否还存在哪些字母,如果不存在则是空指针。此外还有一个bool类型的isEnd,它记录当前节点是否为某个字符串的结尾。
class Trie {
private:
vector<Trie*> children;
bool isEnd;
Trie* searchPrefix(string prefix) {
Trie* node = this;
for (char ch : prefix) {
ch -= 'a';
if (node->children[ch] == nullptr) {
return nullptr;
}
node = node->children[ch];
}
return node;
}
public:
Trie() : children(26), isEnd(false) {}
void insert(string word) {
Trie* node = this;
for (char ch : word) {
ch -= 'a';
if (node->children[ch] == nullptr) {
node->children[ch] = new Trie();
}
node = node->children[ch];
}
node->isEnd = true;
}
bool search(string word) {
Trie* node = this->searchPrefix(word);
return node != nullptr && node->isEnd;
}
bool startsWith(string prefix) {
return this->searchPrefix(prefix) != nullptr;
}
};
2 搜索推荐系统
题目:
给你一个产品数组 products 和一个字符串 searchWord ,products 数组中每个产品都是一个字符串。
请你设计一个推荐系统,在依次输入单词 searchWord 的每一个字母后,推荐 products 数组中前缀与 searchWord 相同的最多三个产品。如果前缀相同的可推荐产品超过三个,请按字典序返回最小的三个。
请你以二维列表的形式,返回在输入 searchWord 每个字母后相应的推荐产品的列表。
题解:
前缀树+优先级队列。
用前缀树把所有单词存储进去。在存储一个单词时,每次用一个Trie指针记录一个字符时,就把该单词记录在这个字符的words队列中。如果队列超过了3个,就pop掉优先级高的单词(最大堆)。
当进行推荐搜索时,每检查一个字符,就将其对应的words队列pop出来就可以了。文章来源:https://www.toymoban.com/news/detail-654558.html
struct Trie {
unordered_map<char, Trie*> child;
priority_queue<string> words;
};
class Solution {
private:
void addWord(Trie* root, const string& word) {
Trie* cur = root;
for (const char& ch: word) {
if (!cur->child.count(ch)) {
cur->child[ch] = new Trie();
}
cur = cur->child[ch];
cur->words.push(word);
if (cur->words.size() > 3) {
cur->words.pop();
}
}
}
public:
vector<vector<string>> suggestedProducts(vector<string>& products, string searchWord) {
Trie* root = new Trie();
for (const string& word: products) {
addWord(root, word);
}
vector<vector<string>> ans;
Trie* cur = root;
bool flag = false;
for (const char& ch: searchWord) {
if (flag || !cur->child.count(ch)) {
ans.emplace_back();
flag = true;
}
else {
cur = cur->child[ch];
vector<string> selects;
while (!cur->words.empty()) {
selects.push_back(cur->words.top());
cur->words.pop();
}
reverse(selects.begin(), selects.end());
ans.push_back(move(selects));
}
}
return ans;
}
};
1 - 2 解题总结
特点:定义一个类对象,它自己代表某个节点,然后它有固定或动态的指针数量。
固定指针数量:已经知道可能得子节点数量,此时可以用vector,然后位置索引即可反映其节点类型。
动态指针数量:没有确切的子节点数量,此时可用set或map。文章来源地址https://www.toymoban.com/news/detail-654558.html
到了这里,关于力扣75——前缀树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!