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

Every day a Leetcode

题目来源:211. 添加与搜索单词 - 数据结构设计

解法1:字典树

字典树(前缀树)是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。前缀树可以用 O(∣S∣) 的时间复杂度完成如下操作,其中 ∣S∣ 是插入字符串或查询前缀的长度:

  • 向字典树中插入字符串 word;
  • 查询字符串 word 是否已经插入到字典树中。

根据题意,WordDictionary 类需要支持添加单词和搜索单词的操作,可以使用字典树实现。

对于添加单词,将单词添加到字典树中即可。

对于搜索单词,从字典树的根结点开始搜索。由于待搜索的单词可能包含点号,因此在搜索过程中需要考虑点号的处理。对于当前字符是字母和点号的情况,分别按照如下方式处理:

  • 如果当前字符是字母,则判断当前字符对应的子结点是否存在,如果子结点存在则移动到子结点,继续搜索下一个字符,如果子结点不存在则说明单词不存在,返回 false;

  • 如果当前字符是点号,由于点号可以表示任何字母,因此需要对当前结点的所有非空子结点继续搜索下一个字符。

重复上述步骤,直到返回 false 或搜索完给定单词的最后一个字符。

如果搜索完给定的单词的最后一个字符,则当搜索到的最后一个结点的 isEnd 为 true 时,给定的单词存在。

特别地,当搜索到点号时,只要存在一个非空子结点可以搜索到给定的单词,即返回 true 。

代码:

/*
 * @lc app=leetcode.cn id=211 lang=cpp
 *
 * [211] 添加与搜索单词 - 数据结构设计
 */

// @lc code=start
struct TrieNode
{
    vector<TrieNode *> child;
    bool isEnd;
    TrieNode() : child(vector<TrieNode *>(26, nullptr)), isEnd(false) {}
};

void insert(TrieNode *root, const string &word)
{
    TrieNode *node = root;
    for (const char &c : word)
    {
        if (node->child[c - 'a'] == nullptr)
            node->child[c - 'a'] = new TrieNode();
        node = node->child[c - 'a'];
    }
    node->isEnd = true;
}

class WordDictionary
{
private:
    TrieNode *trie;

public:
    WordDictionary() : trie(new TrieNode()) {}

    void addWord(string word)
    {
        insert(trie, word);
    }

    bool search(string word)
    {
        return dfs(word, 0, trie);
    }

    bool dfs(const string &word, int index, TrieNode *node)
    {
        if (index == word.size())
            return node->isEnd;
        char ch = word[index];
        if (ch >= 'a' && ch <= 'z')
        {
            TrieNode *child = node->child[ch - 'a'];
            if (child != nullptr && dfs(word, index + 1, child))
                return true;
        }
        else if (ch == '.')
        {
            for (int i = 0; i < 26; i++)
            {
                TrieNode *child = node->child[i];
                if (child != nullptr && dfs(word, index + 1, child))
                    return true;
            }
        }
        return false;
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:初始化为 O(1),添加单词为 O(∣S∣),搜索单词为 O(∣Σ∣∣S∣),其中 ∣S∣ 是每次添加或搜索的单词的长度,Σ 是字符集,这道题中的字符集为全部小写英语字母,∣Σ∣=26。

空间复杂度:O(∣T∣⋅∣Σ∣),其中 ∣T∣ 是所有添加的单词的长度之和,Σ 是字符集,这道题中的字符集为全部小写英语字母,∣Σ∣=26。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值