题目
Trie(发音类似
"try")或者说 前缀树
是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
请你实现 Trie 类:
Trie()
初始化前缀树对象。
void insert(String word)
向前缀树中插入字符串
word
。
boolean search(String word)
如果字符串
word
在前缀树中,返回
true
(即,在检索之前已经插入);否则,返回
false
。
boolean startsWith(String prefix)
如果之前已经插入的字符串 word
的前缀之一为
prefix
,返回 true
;否则,返回
false
。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 输入 ["Trie", "insert", "search", "search", "startsWith", "insert", "search"] [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] 输出 [null, null, true, false, true, null, true]
解释 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
|
提示:
1 <= word.length, prefix.length <= 2000
word
和 prefix
仅由小写英文字母组成
insert
、search
和 startsWith
调用次数 总计 不超过 3 * 104
次
题解
还是先附上自己的代码,用一个哈希表保存字符串,这样可以快速查询和插入,但是对于startWith
没有想到什么很好的解法,就用了遍历的方法,可不可以这样,先插入,再排序,然后看看能不能找到前缀,时间复杂度5%,擦边过了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Trie {
private HashMap<String, String> map;
public Trie() { map = new HashMap<>(); }
public void insert(String word) { map.put(word, word); }
public boolean search(String word) { return map.containsKey(word); }
public boolean startsWith(String prefix) { Set<String> sArray = map.keySet(); for (String s : sArray) { if (s.startsWith(prefix)) { return true; } } return false; } }
|
当然也是要附上常规解法,这题本质上要考字典树:
Trie
为数的每个节点(其实就是每个字母),Trie
有两个成员变量,Trie[] children
表示当前单词某个位置上的字母,isEnd
标记是否是单词的最后一个字母。
初始化自然就是初始化Trie[]
数组的长度26
位,isEnd
为false
;
插入的时候遍历要插入的单词,获取单词的每个字母,如果当前节点的对应该字母位置为null
的话,就要新建一个Trie
对象,表示该单词出现过了,然后node
后移即可。遍历完成之后要标记当前node
的isEnd
为true
;
search
方法调用自定义方法searchPrefix
,返回结果为node != null && isEnd
;searchPrefix
顾名思义,查找前缀,返回要查找的前缀所在的Trie
,search
是全文搜索,自然要判断返回的结果是否是end
;
startWith
方法直接return seatchPrefix(prefix) != null
即可;
自定义方法searchPrefix()
,遍历prefix
每个字母,然后判断该位置上是否有字母也就是说该字母是否在字典树中,没有直接返回null
即可。遍历完prefix
返回node
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| class Trie { private Trie[] children; private boolean isEnd;
public Trie() { children = new Trie[26]; isEnd = false; }
public void insert(String word) { Trie node = this; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); int index = ch - 'a'; if (node.children[index] == null) { node.children[index] = new Trie(); } node = node.children[index]; } node.isEnd = true; }
public boolean search(String word) { Trie node = searchPrefix(word); return node != null && node.isEnd; }
public boolean startsWith(String prefix) { return searchPrefix(prefix) != null; }
private Trie searchPrefix(String prefix) { Trie node = this; for (int i = 0; i < prefix.length(); i++) { char ch = prefix.charAt(i); int index = ch - 'a'; if (node.children[index] == null) { return null; } node = node.children[index]; } return node; } }
|