前缀树是一种树形结构,用于高效的存储和检索字符串。请实现字符串,要求如下:
- Trie() 初始化前缀树对象。
- void insert(String word) 向前缀树中插入字符串 word 。
- boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
- boolean startsWith(String prefix) 如果之前已经插入的字符串word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
示例:
输入
["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
字符长度是26,使用一个长为26的数组做处理。那么字符'a'所在位置就是0='a'-'a',字符'p'所在位置就是'p'-'a';
考虑方法search(word),这个方法要求word在前缀树中,并且word的最后一个字符也能在前缀树中找到并且也是最后一个字符。这里我参考了其他人的实现,需要增加一个标志符是否是结尾字符。
通过上述信息,可以确定单个节点的数据结构:
class Node {
boolean end;
Node[] nodes;public Node() {
this.nodes = new Node[26];
this.end = false;
}
}
insert操作时,用户传入word,那么需要处理每个字符。
这样可以得到如下代码:
public void insert(String word) {
Node temp = root;
for (char c : word.toCharArray()) {
if (temp.nodes[c - 'a'] == null) {
temp.nodes[c - 'a'] = new Node();
}
temp = temp.nodes[c - 'a'];
}
temp.end = true;
}
search执行时,用户传入word进行全字符匹配,这个时候参考insert操作;判断条件做出调整:
这样有代码如下:
public boolean search(String word) {
Node temp = root;
for (char c : word.toCharArray()) {
if (temp.nodes[c - 'a'] == null) {
return false;
}
temp = temp.nodes[c - 'a'];
}
return temp.end;
}
执行startsWith则只需要保证有字符能匹配即可,参考search代码,
那么具体代码实现如下:
public boolean startsWith(String prefix) {
Node temp = root;
for (char c : prefix.toCharArray()) {
if (temp.nodes[c - 'a'] == null) {
return false;
}
temp = temp.nodes[c - 'a'];
}
return true;
}
-
- class Trie {
-
- Node root;
-
- public Trie() {
- this.root = new Node();
- }
-
- public void insert(String word) {
- Node temp = root;
- for (char c : word.toCharArray()) {
- if (temp.nodes[c - 'a'] == null) {
- temp.nodes[c - 'a'] = new Node();
- }
- temp = temp.nodes[c - 'a'];
- }
- temp.end = true;
- }
-
- public boolean search(String word) {
- Node temp = root;
- for (char c : word.toCharArray()) {
- if (temp.nodes[c - 'a'] == null) {
- return false;
- }
- temp = temp.nodes[c - 'a'];
- }
- return temp.end;
- }
-
- public boolean startsWith(String prefix) {
- Node temp = root;
- for (char c : prefix.toCharArray()) {
- if (temp.nodes[c - 'a'] == null) {
- return false;
- }
- temp = temp.nodes[c - 'a'];
- }
- return true;
- }
-
-
- class Node {
- boolean end;
- Node[] nodes;
-
- public Node() {
- this.nodes = new Node[26];
- this.end = false;
- }
- }
-
- public static void main(String[] args) {
- Trie trie = new Trie();
- trie.insert("apple");
- System.out.println(trie.search("apple"));
- System.out.println(trie.search("app"));
- System.out.println(trie.startsWith("app"));
- trie.insert("app");
- System.out.println(trie.search("app"));
- }
- }
这道题是对前缀树的实现,核心是考虑清楚如何构造前缀树的节点。这里我们使用了一个空NODE作为root节点,方便后续的操作。耗时和空间上应该还可以优化,有好的方案欢迎评论,大家一起探讨。