在问 · 算法题解

211. 添加与搜索单词 - 数据结构设计

题目描述

设计一个词典类 WordDictionary,可以往里添加单词,也可以查询某个模式能否匹配到已添加的单词。

- WordDictionary():创建空词典。 - void addWord(word):把 word 加入词典。 - bool search(word):如果词典里有某个单词能与 word 匹配,返回 true,否则返回 false。

查询串 word 中可能出现 '.',它可以匹配任意一个字母。匹配要求长度相同,并且每个位置都对得上。

示例 1
输入:操作 = ["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
参数 = [[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
输出:[null,null,null,null,false,true,true,true]

解释:词典中有 bad、dad、mad:"pad" 不存在;"bad" 存在;".ad" 能匹配三者;"b.." 能匹配 bad。

数据范围

  • 1 <= word.length <= 25
  • addWord 的 word 只含小写英文字母。
  • search 的 word 由 '.' 或小写英文字母组成。
  • addWord 和 search 合计最多调用 10^4 次。

解题思路

用字典树(Trie)存所有单词:每个节点是“字母 → 孩子”的映射,单词结尾打上标记。addWord 沿路径走,缺的孩子就新建。search 用 dfs(node, i):i 到达末尾时看 node 是否是单词结尾;普通字母只走对应的孩子;遇到 . 则对每个孩子递归,只要有一个返回 true 就成功。

为什么正确

dfs(node, i) 为真,当且仅当从 node 出发存在一条路径匹配 word[i:],且终点是某个单词的结尾。

复杂度分析

addWord O(L);search 无通配符时 O(L),最坏 O(26^k · L)(k 为点的个数);空间 O(所有单词总长)。

易错点

走完模式后必须检查结尾标记:只插入 apple 时 search("app") 应为 false。另外通配符的某个分支失败后要继续试其它孩子,不能直接返回 false。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class WordDictionary:
    def __init__(self):
        self.root = {}

    def addWord(self, word: str) -> None:
        node = self.root
        for ch in word:
            node = node.setdefault(ch, {})
        node['$'] = True

    def search(self, word: str) -> bool:
        def dfs(node, i):
            if i == len(word):
                return '$' in node
            ch = word[i]
            if ch == '.':
                return any(dfs(child, i + 1) for k, child in node.items() if k != '$')
            if ch not in node:
                return False
            return dfs(node[ch], i + 1)
        return dfs(self.root, 0)

载入编辑器,自己跑一遍 →

设计 专题的其他题目

查看 设计 全部题目 →