LeetCode 211

实现支持通配符的字典树(Trie):解决单词匹配问题

一、问题描述

我们需要设计一个数据结构,支持以下功能:

  1. 添加新单词
  2. 搜索字符串是否与任何已添加的单词匹配,其中搜索字符串可能包含通配符 .(表示任意字符)。

例如:

  • 插入单词 apple
  • 搜索 app → false
  • 搜索 app. → true

二、方法思路:字典树(Trie)

为什么选择字典树?

字典树是一种高效的树形结构,特别适合处理字符串的前缀匹配问题。其核心优势在于:

  1. 空间效率高:共享公共前缀,减少冗余存储。
  2. 时间复杂度低:插入和查询的时间复杂度均为 O(L)(L 为单词长度)。
  3. 天然支持前缀搜索,易于扩展通配符功能。

通配符 . 的处理逻辑

当搜索遇到 . 时,需要递归遍历当前节点的所有子节点。例如,搜索 app. 时,需检查所有以 app 开头的单词。

三、代码实现(Java)

class WordDictionary {
    private TrieNode root;

    public WordDictionary() {
        root = new TrieNode();
    }

    public void addWord(String word) {
        TrieNode node = root;
        for (char c : word.toCharArray()) {
            if (!node.containsKey(c)) {
                node.put(c, new TrieNode());
            }
            node = node.get(c);
        }
        node.setEnd(); // 标记单词结束
    }

    public boolean search(String word) {
        return searchHelper(word, 0, root);
    }

    private boolean searchHelper(String word, int index, TrieNode node) {
        if (index == word.length()) {
            return node.isEnd(); // 检查是否到达单词末尾
        }
        char c = word.charAt(index);
        if (c == '.') {
            // 遍历所有可能的子节点
            for (char childChar = 'a'; childChar <= 'z'; childChar++) {
                if (node.containsKey(childChar) && 
                    searchHelper(word, index + 1, node.get(childChar))) {
                    return true;
                }
            }
            return false;
        } else {
            // 常规字符匹配
            return node.containsKey(c) && 
                   searchHelper(word, index + 1, node.get(c));
        }
    }

    class TrieNode {
        private TrieNode[] children = new TrieNode[26];
        private boolean isEnd;

        public boolean.containsKey(char c) {
            return children[c - 'a'] != null;
        }

        public TrieNode get(char c) {
            return children[c - 'a'];
        }

        public void put(char c, TrieNode node) {
            children[c - 'a'] = node;
        }

        public void setEnd() {
            isEnd = true;
        }

        public boolean isEnd() {
            return isEnd;
        }
    }
}

四、代码解析

1. TrieNode 类

  • children 数组:存储 26 个字母对应的子节点。
  • isEnd 标记:表示该节点是否是单词的结尾。

2. addWord 方法

  • 逐个字符遍历单词,构建字典树结构。
  • 到达单词末尾时,标记 isEnd 为 true

3. search 方法

  • 递归搜索:从根节点开始,逐个字符匹配。
  • 通配符处理:当遇到 . 时,遍历所有可能的子节点。
  • 终止条件:当遍历完所有字符时,检查当前节点是否为单词结尾。

五、复杂度分析

操作时间复杂度空间复杂度
插入单词O(L)O(L)
搜索单词O(L * 26^k)O (1)(递归栈空间)
  • L:单词长度。
  • k:搜索字符串中 . 的数量。

六、示例说明

测试用例

WordDictionary dict = new WordDictionary();
dict.addWord("apple");
dict.addWord("app");
dict.search("app");      // true
dict.search("app.");     // true(匹配 "apple" 或 "app")
dict.search("ap..");     // true(匹配 "apple")
dict.search("apx.");     // false

七、总结

字典树是解决字符串匹配问题的高效工具,结合递归处理通配符,可以优雅地实现本题要求。这种方法在需要频繁进行插入和搜索操作的场景下表现优异,例如拼写检查、自动补全等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值