LeetCode – Add and Search Word – Data structure design (Java)

Design a data structure that supports the following two operations:

void addWord(word)
bool search(word)

search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter.

Java Solution 1

This problem is similar with Implement Trie. The solution 1 below uses the same definition of a trie node. To handle the “.” case for this problem, we need to search all possible paths, instead of one path.

TrieNode

class TrieNode{
    char c;
    HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
    boolean isLeaf;
 
    public TrieNode() {}
 
    public TrieNode(char c){
        this.c = c;
    }
}

WordDictionary

public class WordDictionary {
    private TrieNode root;
 
    public WordDictionary(){
        root = new TrieNode();
    }
 
    // Adds a word into the data structure.
    public void addWord(String word) {
        HashMap<Character, TrieNode> children = root.children;
 
        for(int i=0; i<word.length(); i++){
            char c = word.charAt(i);
 
            TrieNode t = null;
            if(children.containsKey(c)){
                t = children.get(c);
            }else{
                t = new TrieNode(c);
                children.put(c,t);
            }
 
            children = t.children;
 
            if(i == word.length()-1){
                t.isLeaf = 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 dfsSearch(root.children, word, 0);
 
    }
 
     public boolean dfsSearch(HashMap<Character, TrieNode> children, String word, int start) {
        if(start == word.length()){
            if(children.size()==0) 
                return true; 
            else
                return false;
        }
 
        char c = word.charAt(start);    
 
        if(children.containsKey(c)){
            if(start == word.length()-1 && children.get(c).isLeaf){
                return true;
            }
 
            return dfsSearch(children.get(c).children, word, start+1);
        }else if(c == '.'){
            boolean result = false;
            for(Map.Entry<Character, TrieNode> child: children.entrySet()){
                if(start == word.length()-1 && child.getValue().isLeaf){
                    return true;
                } 
 
                //if any path is true, set result to be true; 
                if(dfsSearch(child.getValue().children, word, start+1)){
                    result = true;
                }
            }
 
            return result;
        }else{
            return false;
        }
    }
}

Java Solution 2 – Using Array Instead of HashMap

class TrieNode{
    TrieNode[] arr;
    boolean isLeaf;
 
    public TrieNode(){
        arr = new TrieNode[26];
    }    
}
 
public class WordDictionary {
    TrieNode root;
 
    public WordDictionary(){
        root = new TrieNode();
    }
    // Adds a word into the data structure.
    public void addWord(String word) {
        TrieNode p= root;
        for(int i=0; i<word.length(); i++){
            char c=word.charAt(i);
            int index = c-'a';
            if(p.arr[index]==null){
                TrieNode temp = new TrieNode();
                p.arr[index]=temp;
                p=temp;
            }else{
                p=p.arr[index];
            }
        }
 
        p.isLeaf=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 dfsSearch(root, word, 0);     
    }
 
   public boolean dfsSearch(TrieNode p, String word, int start) {
		if (p.isLeaf && start == word.length())
			return true;
 
		if (start >= word.length())
			return false;
 
		char c = word.charAt(start);
 
		if (c == '.') {
			boolean tResult = false;
			for (int j = 0; j < 26; j++) {
				if (p.arr[j] != null) {
					if (dfsSearch(p.arr[j], word, start + 1)) {
						tResult = true;
						break;
					}
				}
			}
 
			if (tResult)
				return true;
		} else {
			int index = c - 'a';
 
			if (p.arr[index] != null) {
				return dfsSearch(p.arr[index], word, start + 1);
			} else {
				return false;
			}
		}
 
		return false;
	}
}

4 thoughts on “LeetCode – Add and Search Word – Data structure design (Java)”

  1. Can anyone tell me why this fails on Leetcode 7th test cases

    class WordDictionary {

    class TrieNode {

    Map children;
    Boolean endOfWord;

    public TrieNode() {
    this.children = new HashMap();
    this.endOfWord = false;
    }
    }

    TrieNode root = new TrieNode();
    /** Adds a word into the data structure. */
    public void addWord(String word) {

    if(word == null)
    return ;

    TrieNode curr = root;
    for(int i = 0; i < word.length(); i++){

    char c = word.charAt(i);
    TrieNode trie = curr.children.get(c);
    if(trie == null){
    trie = new TrieNode();
    curr.children.put(c,trie);
    }
    curr = trie;
    }
    curr.endOfWord = 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) {

    TrieNode curr = root;

    LinkedList queue = new LinkedList();
    queue.add(curr);
    int level = 0;
    int len = word.length() - 1;
    while (!queue.isEmpty() && level <= len) {

    char c = word.charAt(level);
    int size = queue.size();
    for (int i = 0; i < size; i++) {

    Map children = queue.remove().children;
    TrieNode temp = children.get(c);
    if (temp != null) {
    if (level == len && temp.endOfWord)
    return true;
    queue.add(temp);

    } else if (c == '.') {
    for(Map.Entry entry : children.entrySet()){
    queue.add(entry.getValue());
    }
    } else
    return false;
    }
    level++;
    }
    return true;

    }
    }

Leave a Comment