作为 Leetcode 刷题指南-树 专题的第二章,本文主要介绍设计字符串搜索和存储结构的结构 字典树 以及相关的Leetcode题型。
关于字典树这一章节,都是套路模板题 啦!你们会看到每一道题都会有插入单词,搜索单词这两个标准模板,剩下的随机应变啦!
- 首先我们先定义作为字典树的节点的结构:
//字典树节点结构
struct TreeNode
{
TreeNode*child[26];
bool isword;
TreeNode() {
memset(child,NULL,sizeof(child));
isword=false;
}
};
树的节点结构里面有两个变量:TreeNode*child[26]是一个TreeNode类型的指针数组,指针是否为空代表着该字母节点是否连着下个字母。布尔类型 isword用来判断单词是否结尾。例如我们要在字典树存储cat以及cdt这两个单词。
2. 上面展示了字典树是如何保存字母的,下面是讲单词加入树的代码实现:
void insert(string word) {
if(word.size()==0)
return;
TreeNode*node=root;
for(int i=0;i<word.size();i++)
{
int ans=word[i]-'a';
if(!node->child[ans]) node->child[ans]=new TreeNode();//例如一开始插入cat,child[2]要创建新节点
node=node->child[ans];//如果本身对应的child[ans]非空,例如我们加了cat后面加入cdt,处理c就不用再新开节点
}
node->isword=true;//标志着单词结束。
}
- 接下来是判断一个单词是否存储在树里面,search函数的结束一般都是i==word.size()哦!
bool search(string word) {
if(word.size()==0)
return false;
TreeNode*node=root;//字典树的根节点
for(int i=0;i<word.size();i++)
{
int ans=word[i]-'a';
if(node->child[ans])
node=node->child[ans];//例如cat单词,首先要判断child[2]是否为空,非空说明字母c保存在树中
else //此时指针更新为child[2],再判断新的节点中child[3](代表字母d)是否为空
return false;
}
if(node&&node->isword==true)//判断最后一个字母是否在树中相应的节点isword==1。声明为单词结束
return true; //例如树中保存着cattql,没有保存cat的话,当我们搜索cat到相对应的t节点,
return false; //isoword==0意味着并非单词结束。
}
通过上面的三个步骤,我们就能实现字典树的基本功能。
208. 实现 Trie (前缀树)
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // 返回 true
trie.search("app"); // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");
trie.search("app"); // 返回 true
说明:
你可以假设所有的输入都是由小写字母 a-z 构成的。
保证所有输入均为非空字符串。
==Method 1: ==
class Trie {
public:
/** Initialize your data structure here. */
struct TreeNode
{
TreeNode*child[26];
bool isword;
TreeNode() {
memset(child,NULL,sizeof(child));
isword=false;
}
};
TreeNode*root;
Trie(){
root=new TreeNode();//初始化树的时候就初始化节点
}
/** Inserts a word into the trie. */
void insert(string word) {
if(word.size()==0)
return;
TreeNode*node=root;
for(int i=0;i<word.size();i++)
{
int ans=word[i]-'a';
if(!node->child[ans]) node->child[ans]=new TreeNode();
node=node->child[ans];
}
node->isword=true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
if(word.size()==0)
return false;
TreeNode*node=root;
for(int i=0;i<word.size();i++)
{
int ans=word[i]-'a';
if(node->child[ans])
node=node->child[ans];
else
return false;
}
if(node&&node->isword==true)
return true;
return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
if(prefix.size()==0)
return false;
TreeNode*node=root;
for(int i=0;i<prefix.size();i++)
{
int ans=prefix[i]-'a';
if(node->child[ans]==NULL)
return false;