图片.png
图片.png

题解

搜索文字,一般会用到 Trie 这种数据结构。而这道题的难点在于处理 word 中存在 . 的情况,因为当处理 . 的时候,需要遍历对应 Trie Node 中的所有字母。

  1. class TrieNode {
  2. isWord: boolean
  3. next = new Map<string, TrieNode>()
  4. constructor(isWord = false) {
  5. this.isWord = isWord
  6. }
  7. }
  8. class WordDictionary {
  9. root: TrieNode
  10. constructor() {
  11. this.root = new TrieNode()
  12. }
  13. addWord(word: string): void {
  14. // 1.遍历 word 中的每个字符
  15. // 2.查看字符是否存在 Trie 中,如果不存在则将字符添加到 Trie 中
  16. let cur = this.root
  17. for(const c of word) {
  18. if (!cur.next.get(c)) {
  19. cur.next.set(c, new TrieNode())
  20. }
  21. cur = cur.next.get(c) as TrieNode
  22. }
  23. cur.isWord = true
  24. }
  25. search(word: string): boolean {
  26. // 1.遍历 word 中的每一个字符
  27. // 2.如果是正常字符,匹配则做递归操作,否则返回 false
  28. // 3.如果碰到 . 字符,则遍历该节点 next 的所有 key
  29. return this.match(this.root, word, 0)
  30. }
  31. match(node: TrieNode, word: string, index: number): boolean {
  32. // 当 index === word.length 的时候,表示 word 中的所有字符已经处理完毕,
  33. // 因此只需要判断节点是否为单词末尾即可。
  34. if (index === word.length) {
  35. return node.isWord
  36. }
  37. const char = word.charAt(index)
  38. if (char !== '.') {
  39. if (!node.next.get(char)) {
  40. return false
  41. }
  42. return this.match(node.next.get(char) as TrieNode, word, index + 1)
  43. } else {
  44. // 遍历当前节点的 next 的所有字符
  45. for (const c of node.next.keys()) {
  46. if (this.match(node.next.get(c) as TrieNode, word, index + 1)) {
  47. return true
  48. }
  49. }
  50. return false
  51. }
  52. }
  53. }