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

  1. 添加与搜索单词 - 数据结构设计
    设计一个支持以下两种操作的数据结构:

void addWord(word)
bool search(word)
search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。

示例:

addWord(“bad”)
addWord(“dad”)
addWord(“mad”)
search(“pad”) -> false
search(“bad”) -> true
search(".ad") -> true
search(“b…”) -> true
说明:

你可以假设所有单词都是由小写字母 a-z 组成的。

class WordDictionary {
    HashSet<String> set;
    /** Initialize your data structure here. */
    public WordDictionary() {
        set = new HashSet<>();
    }

    /** Adds a word into the data structure. */
    public void addWord(String word) {
        set.add(word);
    }

    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    public boolean search(String word) {
        if(set.contains(word)) return true;
        for(String s : set){
            if(equal(s,word)) return true;
        }
        return false;
    }
    private boolean equal(String s, String t){
        char[] n1 = s.toCharArray();
        char[] n2 = t.toCharArray();
        int len1 = n1.length, len2 = n2.length;
        if(len1 != len2) return false;
        for(int i = 0; i < len1; i++){
            if(n1[i] != n2[i] && n2[i] != '.'){
                return false;//碰到这种.以为很麻烦,其实只需要一个表达式,判断一下反面情况即可
            }
        }
        return true;
    }
}

2.优化的话,我们不要将加入的字符串一股脑的放入一个 set 中,可以通过长度进行分类,将长度相同的放到一个 set 中。这样一个一个匹配的时候,规模会减小一些。
分类通过引入,hashmap<Integer, HashSet>

class Node{
    boolean isEnd;
    Node next[];

    public Node(){
        isEnd = false;
        next = new Node[26];
    }

}
class WordDictionary {
    HashMap<Integer, HashSet<String>> map;
    /** Initialize your data structure here. */
    public WordDictionary() {
        map = new HashMap<>();
    }

    /** Adds a word into the data structure. */
    public void addWord(String word) {
        int len = word.length();
        //先判断是否存在长度为len的hashSet
        if(map.containsKey(len)){
            map.get(len).add(word);
        }else{
            HashSet<String> set = new HashSet<>();
            set.add(word);
            map.put(len, set);
        }
    }

    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    public boolean search(String word) {
        HashSet<String> set = map.getOrDefault(word.length(), new HashSet<>());
        //因为上面有可能是空的,所以默认直接返回一个空集合
        if(set.contains(word)){
            return true;
        }
        for(String s : set){
            if(equal(s, word)) return true;
        }
        return false;
    }
    boolean equal(String s, String t){
        int len1 = s.length(), len2 = t.length();
        char c1[] = s.toCharArray();
        char c2[] = t.toCharArray();
        if(len1 != len2) return false;
        for(int i =0; i < len1; i++){
            if(c1[i] != c2[i] && c2[i] != '.'){
                return false;
            }
        }
        return true;
    }
}

3.利用前缀树的概念

class Node{
    boolean isEnd;
    Node next[];

    public Node(){
        isEnd = false;
        next = new Node[26];
    }

}
class WordDictionary {
    Node root;
    /** Initialize your data structure here. */
    public WordDictionary() {
        root = new Node();
    }

    /** Adds a word into the data structure. */
    public void addWord(String word) {
        //这个代码是没啥变化的,就是丰富每一个分支,没连的连上
        char[] ch = word.toCharArray();
        int len = ch.length;
        Node now = root;
        for(int i = 0; i < len; i++){
            if(now.next[ch[i] - 'a'] == null){
                now.next[ch[i] - 'a'] = new Node();
            }
            now = now.next[ch[i] - 'a'];
        }
        now.isEnd = true;
    }

    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    public boolean search(String word) {
        //因为存在.特殊运算符,所以递推每一种情况
        //同时需要引入一个参数,方便递推
        return dfs(word, root);
    }
    public boolean dfs(String s, Node root){
        char ch[] = s.toCharArray();
        Node now = root;
        int len = ch.length;
        for(int i = 0; i < len; i++){
            if(ch[i] == '.'){//如果当前为.则需要对26个分支任意选择(指的是存在不为null的分支)
                for(int j = 0; j < 26; j++){
                    if(now.next[j] != null){//只遍历那些不为null的分支
                        if(dfs(s.substring(i + 1), now.next[j])) return true;
                    }
                }
                return false;
            }
            //如果不是特殊符号
            now = now.next[ch[i] - 'a'];
            if(now == null) return false;

        }
        return now.isEnd;//最终还要判断是否为前缀
    }
}
展开阅读全文
©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读