leetcode-676:实现一个魔法字典

简介: leetcode-676:实现一个魔法字典

题目

题目连接

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

实现 MagicDictionary 类:

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

示例:

输入
["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

解题

方法一:字典树+dfs

参考链接

字典树的构建就是常规的构建方法

就dfs有所区别

dfs里面有两种情况

  • 当前字符在字典树中存在,继续dfs
  • 暴力遍历26个字母,继续dfs。通过limit标志位去标志,只能更换一次字母。
class Trie{
public:
    bool isEnd=false;
    vector<Trie*> next=vector<Trie*>(26,nullptr);
};
class MagicDictionary {
public:
    Trie* trie=new Trie();
    MagicDictionary() {
    }
    //api
    void buildDict(vector<string> dictionary) {
        for(string& word:dictionary){
            insert(word);
        }
    }
    //api
    bool search(string searchWord) {
        return dfs(trie,searchWord,0,1);
    }   
    bool dfs(Trie* node,string& word,int startIndex,int limit){//limit表示是否还能修改字母
        if(startIndex==word.size()){
            return limit==0&&node->isEnd;
        }
        int i=word[startIndex]-'a';
        if(node->next[i]){//如果当前前缀能在字典树中找到,那么就接着dfs
            if(dfs(node->next[i],word,startIndex+1,limit)) return true;
        }
        if(limit==1){//如果没有修改过字母,就暴力遍历26个字母
            for(int j=0;j<26;j++){
                if(j!=i&&node->next[j]){
                    if(dfs(node->next[j],word,startIndex+1,limit-1)) return true;
                }
            }
        }
        return false;
    }
    void insert(string& word){
        Trie* node=trie;
        for(char c:word){
            if(node->next[c-'a']==nullptr){
                node->next[c-'a']=new Trie();
            }
            node=node->next[c-'a'];
        }
        node->isEnd=true;
    }
};

相关文章
|
存储 Swift C++
41 Swift不透明类型
Swift不透明类型
117 0
|
XML 数据可视化 数据格式
camunda-modeler(5.9.0)介绍及下载
camunda-modeler(5.9.0)介绍及下载
1507 1
|
Java Go C++
Golang每日一练(leetDay0101) 最长递增子序列I\II\个数
Golang每日一练(leetDay0101) 最长递增子序列I\II\个数
128 0
Golang每日一练(leetDay0101) 最长递增子序列I\II\个数
|
人工智能
leetcode-每日一题731. 我的日程安排表 II
题目需要我们判断在重复的预定时间里,有三重预定的返回false,那我们可以定义一个pair结构体用来表示时间段,MyCalendarTwo结构体用来存成功预定的时间段booked切片,和有重复预定的时间段overlaps切片,overlaps切片用来判断新进的时间段是否跟overlaps有重合预定的情况,若有则返回false,没有则true
238 0
leetcode-每日一题731. 我的日程安排表 II
|
IDE 开发工具 Android开发
使用rxjava创建一个rxbus事件处理框架
RxJava已经出现很多个年头了,但是依然被很多公司使用,如果现在还对RxJava了解的不够透彻, 可以看这个系列对它的分析:相信看完后你对它会有个更全面的认识。 这个系列主要从下面几个方面来讲解: **RxJava基本操作符使用** **RxJava响应式编程是如何实现的** **RxJava的背压机制及Flowable是如何实现背压的** **RxJava的线程切换原理
|
API iOS开发
iOS底层原理:Method Swizzling原理和注意事项(一)
Method Swizzling的含义是方法交换,其核心内容是使用runtime api在运行时将一个方法的实现替换成另一个方法的实现。我们利用它可以替换系统或者我们自定义类的方法实现,进而达到我们的特殊目的,这就是我们常说的iOS黑魔法。
iOS底层原理:Method Swizzling原理和注意事项(一)
|
API iOS开发
iOS Principle:Runloop(上)
iOS Principle:Runloop(上)
266 0
iOS Principle:Runloop(上)
|
API iOS开发
iOS底层原理:Method Swizzling原理和注意事项(二)
Method Swizzling的含义是方法交换,其核心内容是使用runtime api在运行时将一个方法的实现替换成另一个方法的实现。我们利用它可以替换系统或者我们自定义类的方法实现,进而达到我们的特殊目的,这就是我们常说的iOS黑魔法。
iOS底层原理:Method Swizzling原理和注意事项(二)
|
JavaScript 搜索推荐 前端开发
一次解决页面特效问题的排查记录
大家在做项目的时候,肯定会和我一样,碰到各种各样的问题,然后熟练的打开搜索引擎,输入些关键字,开始解决问题。最近在做一个效果,中间就碰到了各种问题,接下来我把解决这个问题的过程发出来分享下,也算是我的一个小心得。 要做的效果其实很简单,就是在做支付的时候,出现一个弹出层,然后跳到一张新页面,类似于下面两张图片的效果:
一次解决页面特效问题的排查记录