1、思路
题目只包含26个小写字母,那么可以用一个26叉树来表示前缀树。
2、智能指针:shared_ptr
之所以使用shared_ptr
是为了防止内存泄漏,比如用:
shared_ptr<TrieNode> findPrefix(string& prefix)
来代替:
Trie* findPrefix(string& prefix)
这样指针在返回后会自动释放内存。
智能指针的头文件在<memory>
中,其推荐的声明方法为:
//声明一个指针,指向10个int整型的数组,当指针离开作用域后,所指空间会被自动释放
shared_ptr<int> p = make_shared<int>(10);
3、题解代码如下:
class Trie {
private:
struct TrieNode //26叉树结构体
{
bool isWord;
vector<shared_ptr<TrieNode>> children;
TrieNode():isWord(false), children(26, nullptr){} //构造函数成员列表初始化
};
shared_ptr<TrieNode> findPrefix(string& prefix) //查找前缀的方法
{
auto node = root;
for (int i = 0; i < prefix.length() && node != nullptr; ++ i)
{
node = node->children[prefix[i] - 'a'];
}
return node; //若是前缀就返回最后一个字母所在的node,否则返回nullptr
}
shared_ptr<TrieNode> root;
public:
Trie() {
root = make_shared<TrieNode>(); //初始化智能指针
}
//往前缀树中插入单词
void insert(string word) {
auto node = root; //node为当前节点,从头节点开始
for (auto &ch : word) //遍历每个字母,若字母对应的节点不存在,则创建它
{
if (node->children[ch - 'a'] == nullptr)
{
node->children[ch - 'a'] = make_shared<TrieNode>();
}
node = node->children[ch - 'a']; //进入到对应的子树节点中,开始下一轮插入
}
node->isWord = true; //整个单词遍历完后,将最后一个节点标记为单词结尾
}
//前缀树中查找单词
bool search(string word) {
auto node = findPrefix(word);
return node != nullptr && node->isWord == true;
}
//前缀树中查找前缀
bool startsWith(string prefix) {
return findPrefix(prefix) != nullptr;
}
};
之前有个朋友在微软一面的时候被要求手撕前缀树,太难了啊这。