🚩传送门:力扣题目

题目

前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

  • _Trie()_ 初始化前缀树对象。
  • _void insert(String word)_ 向前缀树中插入字符串 word 。
  • _boolean search(String word)_ 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
  • _boolean startsWith(String prefix)_ 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false

解题思路:字典树

[LC]208. 实现 Trie (前缀树) - 图1,又称前缀树或字典树,是一棵有根树,其每个节点[LC]208. 实现 Trie (前缀树) - 图2包含以下字段:

  • 数据域 [LC]208. 实现 Trie (前缀树) - 图3,存储当前节点的字符
  • 指向子节点的指针数组 [LC]208. 实现 Trie (前缀树) - 图4。对于本题而言,用 [LC]208. 实现 Trie (前缀树) - 图5 做为树的指针。
  • 布尔字段 [LC]208. 实现 Trie (前缀树) - 图6,表示该节点是否为字符串的结尾。

插入字符串

我们从字典树的根开始,插入字符串。对于当前字符对应的子节点,有两种情况:

  • 子节点存在。沿着指针移动到子节点,继续处理下一个字符。
  • 子节点不存在。创建一个新的子节点,记录在 [LC]208. 实现 Trie (前缀树) - 图7上,然后沿着指针移动到子节点,继续搜索下一个字符。

重复以上步骤,直到处理字符串的最后一个字符,然后将当前节点标记为字符串的结尾。

查找前缀

我们从字典树的根开始,查找前缀。对于当前字符对应的子节点,有两种情况:

  • 子节点存在。沿着指针移动到子节点,继续搜索下一个字符。
  • 子节点不存在。说明字典树中不包含该前缀,返回空指针。

重复以上步骤,直到返回空指针或搜索完前缀的最后一个字符。

复杂度分析

时间复杂度:[LC]208. 实现 Trie (前缀树) - 图8,其余操作为 [LC]208. 实现 Trie (前缀树) - 图9,其中 [LC]208. 实现 Trie (前缀树) - 图10 是每次插入或查询的字符串的长度。

空间复杂度:[LC]208. 实现 Trie (前缀树) - 图11,其中 [LC]208. 实现 Trie (前缀树) - 图12 为所有插入字符串的长度之和

我的代码

  1. class Trie {
  2. TreeNode root;
  3. // 树结点
  4. public class TreeNode {
  5. char val;
  6. boolean iscomplete;
  7. HashMap<Character, TreeNode> nextChild;
  8. TreeNode(char val) {
  9. this.val = val;
  10. nextChild = new HashMap<Character, TreeNode>();
  11. iscomplete = false;
  12. }
  13. }
  14. public Trie() {
  15. root = new TreeNode('0');
  16. }
  17. public void insert(String word) {
  18. char[] words = word.toCharArray();
  19. TreeNode cur = root;
  20. for (int i = 0; i < words.length; i++) {
  21. TreeNode next = cur.nextChild.get(words[i]);
  22. if (next == null) {
  23. // 插入新节点
  24. cur.nextChild.put(words[i], new TreeNode(words[i]));
  25. cur = cur.nextChild.get(words[i]);
  26. } else {
  27. cur = next;
  28. }
  29. }
  30. cur.iscomplete = true;
  31. }
  32. public boolean search(String word) {
  33. TreeNode cur = root;
  34. char[] words = word.toCharArray();
  35. for (int i = 0; i < words.length; i++) {
  36. TreeNode next = cur.nextChild.get(words[i]);
  37. if (next == null) return false;
  38. cur = next;
  39. }
  40. if (cur.iscomplete)
  41. return true;
  42. return false;
  43. }
  44. public boolean startsWith(String prefix) {
  45. TreeNode cur = root;
  46. char[] words = prefix.toCharArray();
  47. for (int i = 0; i < words.length; i++) {
  48. TreeNode next = cur.nextChild.get(words[i]);
  49. if (next == null) return false;
  50. cur = next;
  51. }
  52. return true;
  53. }
  54. }