返回

LeetCode 211. 添加与搜索单词(数据结构设计):JavaScript(正则 + Trie + DFS)

前端

在日常开发中,我们经常会遇到搜索相关的问题。LeetCode 211题正是这样一个经典的题目,它要求我们设计一个支持添加和搜索单词的数据结构,并提供搜索建议和自动补全功能。

问题分析

首先,我们需要设计一个高效的数据结构来存储单词。常见的解决方案包括哈希表、字典树(Trie)和二叉查找树。

  • 哈希表:哈希表是一种将键值对存储在数组中的数据结构。它通过哈希函数将键映射到数组中的某个位置,从而实现快速查找。然而,哈希表并不适合存储大量字符串,因为字符串的比较效率较低。
  • 字典树(Trie):字典树是一种树状结构,每个节点代表一个字符。通过沿字典树的路径,我们可以快速找到一个单词。字典树非常适合存储字符串,因为它可以有效地利用字符串的公共前缀。
  • 二叉查找树:二叉查找树是一种二叉树,其中每个节点代表一个字符串。通过沿二叉查找树的路径,我们可以快速找到一个单词。二叉查找树也适合存储字符串,但它的插入和删除操作比字典树更复杂。

在LeetCode 211题中,我们使用字典树来存储单词。字典树具有以下优点:

  • 查询效率高:字典树可以快速查找一个单词,时间复杂度为O(k),其中k是单词的长度。
  • 节省存储空间:字典树可以有效地利用字符串的公共前缀,从而节省存储空间。
  • 支持模糊搜索:字典树可以支持模糊搜索,即查找与给定单词相似度较高的单词。

代码实现

class TrieNode {
  constructor() {
    this.children = new Map();
    this.isWord = false;
  }
}

class WordDictionary {
  constructor() {
    this.root = new TrieNode();
  }

  addWord(word) {
    let node = this.root;
    for (const char of word) {
      if (!node.children.has(char)) {
        node.children.set(char, new TrieNode());
      }
      node = node.children.get(char);
    }
    node.isWord = true;
  }

  search(word) {
    return this._search(word, this.root);
  }

  _search(word, node) {
    for (let i = 0; i < word.length; i++) {
      const char = word[i];
      if (char === '.') {
        for (const child of node.children.values()) {
          if (this._search(word.substring(i + 1), child)) {
            return true;
          }
        }
        return false;
      } else if (!node.children.has(char)) {
        return false;
      }
      node = node.children.get(char);
    }
    return node.isWord;
  }
}

const wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
console.log(wordDictionary.search("pad")); // false
console.log(wordDictionary.search("bad")); // true
console.log(wordDictionary.search(".ad")); // true
console.log(wordDictionary.search("b..")); // true

时间复杂度

  • 添加单词:O(k),其中k是单词的长度。
  • 搜索单词:O(k),其中k是单词的长度。

空间复杂度

  • 字典树的大小与单词表的大小成正比。在最坏的情况下,字典树的大小为O(n * k),其中n是单词表的大小,k是单词的平均长度。

应用场景

LeetCode 211题的解决方案可以应用于各种场景,包括:

  • 搜索建议:当用户在搜索框中输入查询时,搜索引擎会提供相关的搜索建议。这些建议通常是基于用户输入的查询以及用户的搜索历史。
  • 自动补全:当用户在文本框中输入内容时,文本编辑器会提供自动补全功能。自动补全功能会根据用户输入的内容提供相关的内容建议。
  • 拼写检查:拼写检查器会检查用户输入的单词是否拼写正确。如果单词拼写错误,拼写检查器会提供正确的拼写建议。