676. 实现一个魔法字典

题目描述:

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

  实现 MagicDictionary 类:

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

 

提示:

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

 

示例:

输入
["MagicDictionary", "buildDict", "search", "search", "search", "search", "search"] 
[[], [["hello","hallo","leetcode","judge"]], ["hello"], ["hallo"], ["hell"], ["leetcodd"], ["judge"]] 输出 [
null, null, true, true, false, false]

 

解题思路:

  • 首先,使用字典树来进行字符串的存储,在这里,字典树的初始键设为字符串长度,当search时没找到符合的长度时直接返回 false;
  • 字典建立过程如下:

            

 

  • 在search中,使用深度优先搜索+递归的方法,设计变量count来表示字符能被替换次数,初始值为1

    当前节点node的key与待查询字符串的第index个字符相同时,沿着node的children往下搜索;

    当前节点node的key与待查询字符串的第index个字符不相同时,count减1,也沿着node的children往下搜索;

  • 递归结束条件有两个:

  ①count的值小于0,表示递归过程中字符被替换次数超过1次,直接返回false;

  ②index到达待查询字符串末尾,此时根据count是否等于0来判断待查询字符串是否满足条件(count==0表示字符串中的某个字符刚好被替换一次,返回true;count>0表示与字典树中字符串相同,返回false)。

 

  要注意的是,对于字典树中的每一层,我们应该要遍历所有的节点(相同则往下走,不同则替换次数减1后往下走)。为了简化循环,设计一个变量 f 作为信号,当前面深度优先搜索过程中找到符合条件的路径时,接下来的每一次循环都直接跳过。注意,代码中使用的是forEach方法,方法里的代码块是它的执行函数而不是循环结构,要用return来返回函数进行循环跳过,而不是break。

 

代码实现:

复制代码
var MagicDictionary = function() {
    this.map = new Map();
};

/**
 * @param {string[]} dictionary
 * @return {void}
 */
MagicDictionary.prototype.buildDict = function(dictionary) {
    for(const word of dictionary){
        let len = word.length;
        let list = new Map();
        if(this.map.has(len)){
            list = this.map.get(len);
        }else{
            this.map.set(len,list);
        }
        let i=0;
        let cur = list;
        while(i<len){
            if(cur.has(word[i])){
                cur = cur.get(word[i]);
                i++;
            }else{
                let children = new Map();
                cur.set(word[i],children);
                i++;
                cur = children;
            }
        }
    }
};

/**
 * @param {string} searchWord
 * @return {boolean}
 */
MagicDictionary.prototype.search = function(searchWord) {
    let len = searchWord.length;
    function dfs(searchWord,index,map,count){
        if(count<0){
            return false;
        }
        if(index==searchWord.length){
            return count==0;
        }
        let f = false;
        map.forEach((value,key)=>{
            if(f){
                return;
            }
            if(key!==searchWord[index]){
                f = dfs(searchWord,index+1,value,count-1)
            }else {
                f = dfs(searchWord,index+1,value,count);
            }
        })
        return f;
    }
    if(this.map.has(len)){
        let cur = this.map.get(len);
        return dfs(searchWord,0,cur,1);
    }else{
        return false;
    }
};


/**
 * Your MagicDictionary object will be instantiated and called as such:
 * var obj = new MagicDictionary()
 * obj.buildDict(dictionary)
 * var param_2 = obj.search(searchWord)
 */
复制代码

 

posted @   ˙鲨鱼辣椒ゝ  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示