Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目:题目具体可看 208. 实现 Trie (前缀树)) ,要求实现前缀树的初始化、插入、查找以及查询前缀。
解题思路
在没有理解前缀树是什么的时候,我想的是用一个list存储每次插入的元素,当查询的时候就遍历list,而当找前缀的时候则遍历list将每个元素按照给的前缀进行切割,如果相等就判断为true等等...如下是代码的实现:
class Trie {
ArrayList<String> list = null;
public Trie() {
list = new ArrayList();
}
public void insert(String word) {
list.add(word);
}
public boolean search(String word) {
for(String s:list){
if(s.equals(word)){
return true;
}
}
return false;
}
public boolean startsWith(String prefix) {
for(String s:list){
if(s.length()>=prefix.length()&&prefix.equals(s.substring(0, prefix.length()))){
return true;
}
}
return false;
}
}
最后居然AC了,运行的时间为423ms。额,没见过这么久的。之后去具体查了一下前缀树是什么以及有什么意义。可以看这篇文章:什么是前缀树--打开了我的新思路。
前缀树
简单来说,前缀树就是一个多路树形结构,树的每个节点存储的都是一个字符,根节点为空。从根节点到叶子节点的某条路径连接起来就是该节点对应的字符串等等。如下图就是一个简单的前缀树:
前缀树可以统计词频、过滤敏感词以及词自动填充等。总之前缀树有着巨大的应用前景。
那么回到本题,前缀树的特点是根节点下面跟着的是多叉树,多叉树下的节点下面依然是多叉树,那么如果对象是多元的,我们可以使用Map来存储每棵树的节点。其中key为每个节点的值,而value则为每个节点的子节点。之后对Map进行操作即可,需要注意的是:Map中的每个值都是一个字符。
由本题的条件可知,其输入的都是字符串,而只包含字母的字符串的范围为0-25,并且因为数组的查询速度是较优的,因此可考虑将每个节点的子节点用一个同样结构的数组来代替,数组的每个元素的索引就对应字符的'a'-'z',插入之前先查询,如果该结构不为空则可以直接插入,搜索等操作也类似。设计的前缀树数据结构为:
class TrieNode{
private boolean isEnd;
TrieNode[] next;
public TrieNode(){
isEnd = false;
next = new TrieNode[26];
}
}
此处设计isEnd来记录插入单词的结尾,这样当查询时候会用到,完整代码如下:
class Trie {
class TrieNode{
private boolean isEnd;
TrieNode[] next;
public TrieNode(){
isEnd = false;
next = new TrieNode[26];
}
}
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode tempNode = root;
for(char c:word.toCharArray()){
if(tempNode.next[c-'a']==null){
tempNode.next[c-'a'] = new TrieNode();
}
tempNode = tempNode.next[c-'a'];
}
tempNode.isEnd = true;
public boolean search(String word) {
TrieNode tempNode = root;
for(char c:word.toCharArray()){
if(tempNode.next[c-'a']==null){
return false;
}
tempNode = tempNode.next[c-'a'];
}
return tempNode.isEnd;
}
public boolean startsWith(String prefix) {
TrieNode tempNode = root;
for(char c:prefix.toCharArray()){
if(tempNode.next[c-'a']==null) return false;
tempNode = tempNode.next[c-'a'];
}
return true;
}
}