【C/C++】676. 实现一个魔法字典

230 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情


题目链接:676. 实现一个魔法字典

题目描述

设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 。 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于你构建的字典中。

实现 MagicDictionary 类:

  • MagicDictionary() 初始化对象
  • void buildDict(String[] dictionary) 使用字符串数组 dictionary 设定该数据结构,dictionary 中的字符串互不相同
  • bool search(String searchWord) 给定一个字符串 searchWord ,判定能否只将字符串中 一个 字母换成另一个字母,使得所形成的新字符串能够与字典中的任一字符串匹配。如果可以,返回 true ;否则,返回 false

提示:

  • 1 dictionary.length1001 \leqslant dictionary.length \leqslant 100
  • 1 dictionary[i].length1001 \leqslant dictionary[i].length \leqslant 100
  • dictionary[i] 仅由小写英文字母组成
  • dictionary 中的所有字符串 互不相同
  • 1 searchWord.length1001 \leqslant searchWord.length \leqslant 100
  • searchWord 仅由小写英文字母组成
  • buildDict 仅在 search 之前调用一次
  • 最多调用 100search

示例 1:

输入
["MagicDictionary", "buildDict", "search", "search", "search", "search"]
[[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]]
输出
[null, null, false, true, false, false]

解释
MagicDictionary magicDictionary = new MagicDictionary();
magicDictionary.buildDict(["hello", "leetcode"]);
magicDictionary.search("hello"); // 返回 False
magicDictionary.search("hhllo"); // 将第二个 'h' 替换为 'e' 可以匹配 "hello" ,所以返回 True
magicDictionary.search("hell"); // 返回 False
magicDictionary.search("leetcoded"); // 返回 False

整理题意

题目给定一个字符串数组 dictionary,然后每次给出一个单词 searchWord,需要我们判断是否可以通过改变 searchWord 的中的一个字符使得 searchWord 与字符串数组 dictionary 中某一个字符串相同。

需要注意的是 必须 改变 searchWord 的中的一个字符,且仅能改变一个字符。

解题思路分析

由于题目数据范围较小,我们可以对于每次查询的 searchWord 在字符串数组 dictionary 中进行暴力匹配,查找字符串数组 dictionary 中的字符串是否存在与 searchWord 长度相同且仅有一个字符不相同的字符串。

具体实现

  1. 将给定字符串数组 dictionary 进行存储;
  2. 对于每次给定的 searchWord,遍历字符串数组 dictionary,匹配与 searchWord 长度相同且仅有一个字符不相同的字符串。
  3. 如果匹配成功返回 true,否则返回 false

复杂度分析

  • 时间复杂度:O(qnl)O(qnl),其中 n 是数组 dictionary 的长度,l 是数组 dictionary 中字符串的平均长度,q 是函数 search(searchWord) 的调用次数。
  • 空间复杂度:O(nl)O(nl),即为数组需要使用的空间。

代码实现

class MagicDictionary {
private:
    vector<string> s;
public:
    MagicDictionary() {
        s.clear();
    }
    
    void buildDict(vector<string> dictionary) {
        s = dictionary;
    }
    
    bool search(string searchWord) {
        int len = searchWord.length();
        int n = s.size();
        for(int i = 0; i < n; i++){
            //当长度不匹配时直接跳过
            if(s[i].length() != len) continue;
            //f记录不相同的字符个数
            int f = 0;
            for(int j = 0; j < len; j++){
                if(s[i][j] != searchWord[j]) f++;
                //如果有两个字符不相同也可以直接跳过
                if(f >= 2) break;
            }
            if(f == 1) return true;
        }
        return false;
    }
};

/**
 * Your MagicDictionary object will be instantiated and called as such:
 * MagicDictionary* obj = new MagicDictionary();
 * obj->buildDict(dictionary);
 * bool param_2 = obj->search(searchWord);
 */

总结

  • 由于该题数据范围较小,采用暴力枚举匹配的方法更优。同时该题如果扩大数据范围,需要使用字典树来优化枚举,在字典树上进行搜索。在查询时,我们可以使用递归 + 回溯的方法进行判断。
  • 在匹配字符串时,对于长度不相等的字符串可以跳过,同时采用一个变量记录不同字符的个数,当不同字符的个数超过 1 个时也可以直接跳过,从而减少循环次数。
  • 测试结果:

676.png

结束语

世界上没有人是完美的,每个人都有优点和缺点,不必因为一些缺憾而郁郁寡欢,也不要因一时错过而过多地埋怨自己。只有学会欣赏自己的优点和长处,充分接纳自己,才能散发出更多的光芒!新的一天,加油!