写在前面
前缀树这道题目208. 实现 Trie (前缀树) - 力扣(LeetCode)自己刷过好几遍,每一次都感觉差点意思,今天又再次刷到这道题目,将自己多次刷过之后的一点思考与感悟写如下:
关于前缀树具体如何实现请参考如下链接,在此只阐述自己的思考。【数据结构与算法系列】——前缀树(字典树)、后缀树,主要用于海量数据的查找和去重问题_域名匹配 前缀树 后缀树-CSDN博客
实现前缀树需要定义一个前缀树的类:
class TrieNode{ boolean end; // 定义每一个节点的结束标志,如果其为true表示某个单词完全在树中终止 TrieNode next = new TrieNode[26] // 存放单词中的具体的字母 }
- 今天刷这道题目让我联想到二叉树数据结构中每一个节点都有一个val用于存储当前节点对应的值,想到这里之后思考为什么前缀树数据结构中每个节点不设置一个具体的属性如:char val用于存储当前节点的属性值?
- 前缀树结构中的next指针属性已经定义了当前前缀树中可以存储的具体的字母值,也就是new TrieNode[26],表示每个TrieNode节点可以存储26个字母,这里的存储26个字母并不是真正将26个字母存储到对应的位置,而是使用字母和下标的映射关系来表示存储,'a'对应下标0,同时next['a' - '0']需要存储下一级的TrieNode节点,用于实现向下延深的功能。
- cur.next[ch - '0'] = new TrieNode()。如果使用next[ch - '0']存储具体属性值则不能实现树的功能。
- 进一步思考二叉树中left和right指向下一级二叉树,在前缀树中变为了一个字符对应的下标指向下一级的26个字符。
- 前缀树数据结构中并不存储实际对应的字符值,而是通过数组下标和实际字符值建立映射关系。
代码实现
class Trie {
public class TrieNode{
boolean end;
TrieNode[] next = new TrieNode[26];
}
public TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode cur = root;
for(int i = 0; i < word.length(); i++){
char ch = word.charAt(i);
if(cur.next[ch - 'a'] == null){
cur.next[ch - 'a'] = new TrieNode();
}
cur = cur.next[ch - 'a'];
}
cur.end = true;
}
public boolean search(String word) {
TrieNode cur = root;
for(int i = 0; i < word.length(); i++){
char ch = word.charAt(i);
if(cur.next[ch - 'a'] == null) return false;
cur = cur.next[ch - 'a'];
}
return cur.end;
}
public boolean startsWith(String prefix) {
TrieNode cur = root;
for(int i = 0; i < prefix.length(); i++){
char ch = prefix.charAt(i);
if(cur.next[ch - 'a'] == null) return false;
cur = cur.next[ch - 'a'];
}
return true;
}
}