《leetCode》:Add and Search Word - Data structure design
来源:互联网 发布:软件规格需求说明书 编辑:程序博客网 时间:2024/04/28 11:00
题目
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.
For example:
addWord("bad")addWord("dad")addWord("mad")search("pad") -> falsesearch("bad") -> truesearch(".ad") -> truesearch("b..") -> true
Note:
You may assume that all words are consist of lowercase letters a-z.
思路一:报超时
直接借用一个容器来添加和搜索匹配,实现代码如下:
public class WordDictionary { // Adds a word into the data structure. List<String> words = new ArrayList<String> (); public void addWord(String word) { words.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) { for(String str:words){ if(str.matches(word)){ return true; } } return false; } }
思路二
根据题目的提示,使用trie结构。
修改trie结构中的searchWord方法即可。在实现Trie结构的searchWord方法中并没有考虑处理通配符的情况,而这里我们需要考虑。
考虑的思路为:如果此通配符是单词的最后一个字符,则只需要判断该节点下是否还存在节点的leaf属性为true的节点。如果此通配符不是单词的最后一个字符,则需要遍历该节点的所有子节点所代表的情况。
代码如下:
public class WordDictionary { // Adds a word into the data structure. private Trie t = new Trie(); public void addWord(String word) { t.insert(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) { //先将word最后的点点给去掉 return t.search(word); } class TrieNode { // Initialize your data structure here. public boolean leaf;//标识一个word到此结束 public Map<Character,TrieNode> childrens = new HashMap<Character,TrieNode>(); public TrieNode() { } } class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } // Inserts a word into the trie. public void insert(String word) { Map<Character,TrieNode> childrens = root.childrens; for(int i=0;i<word.length();i++){ Character ch =word.charAt(i); TrieNode t = null; if(childrens.containsKey(ch)){ t = childrens.get(ch); } else{//此字符是一个新的分支 t = new TrieNode(); childrens.put(ch, t); } //继续寻找或插入第二个字符 childrens = t.childrens; //设置单词的标识 if(i==word.length()-1){ t.leaf = true; } } } // Returns if the word is in the trie. public boolean search(String word) { TrieNode t = searchWord(word,root); return t!=null&&t.leaf; } public TrieNode searchWord(String word,TrieNode node){ Map<Character,TrieNode> childrens = node.childrens; TrieNode t = null; for(int i=0;i<word.length();i++){ Character ch = word.charAt(i); if(ch=='.'){ Set<Character> set = childrens.keySet(); TrieNode tt = null; //如果是最后一个通配符,则只要还存在分支节点的leaf为true,则就能匹配 if(i==word.length()-1){ for(Character c :set){ tt = childrens.get(c); if(tt.leaf){ return tt; } } return null; } //对每个分支进行匹配检查 for(Character c:set){ t = childrens.get(c); tt =searchWord(word.substring(i+1),t); if(tt!=null){ return tt; } } return null;//所有的都没有找到; } else if(ch!='.'&&!childrens.containsKey(ch)){//如果没有此分支,则返回null return null; } else{//如果有此分支,则更新childrens t = childrens.get(ch); childrens = t.childrens; } } return t; } // Returns if there is any word in the trie // that starts with the given prefix. public boolean startsWith(String prefix) { TrieNode t = searchWord(prefix,root); return t!=null; } } // public static void main(String[] args){ // WordDictionary wd = new WordDictionary(); // wd.addWord("apple"); // String str = "......"; // System.out.println(wd.search(str)); // } } // Your WordDictionary object will be instantiated and called as such: // WordDictionary wordDictionary = new WordDictionary(); // wordDictionary.addWord("word"); // wordDictionary.search("pattern");
很遗憾,此代码没有AC,只能通过11/13个case。
代码重新进行了分析,实在是不知道问题出现在哪。而leetcode提供的测试用例实在是过于庞大,不方便debug。
对以上的代码进行了重构,如下:
public class WordDictionary { // Adds a word into the data structure. private TrieNode root = new TrieNode(); public void addWord(String word) { Map<Character,TrieNode> childrens = root.childrens; for(int i=0;i<word.length();i++){ Character ch =word.charAt(i); TrieNode t = null; if(childrens.containsKey(ch)){ t = childrens.get(ch); } else{//此字符是一个新的分支 t = new TrieNode(); childrens.put(ch, t); } //继续寻找或插入第二个字符 childrens = t.childrens; //设置单词的标识 if(i==word.length()-1){ t.leaf = 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 searchWord(word,root); } private boolean searchWord(String word,TrieNode node) { if(word==null||node ==null){ return false; } if(word.length()==0){ return node.leaf; } Map<Character,TrieNode> childrens = node.childrens; Character ch =word.charAt(0); if(ch=='.'){ for(Character c:childrens.keySet()){ if(searchWord(word.substring(1),childrens.get(c))){ return true; } } } else if(ch!='.'&&!childrens.containsKey(ch)){ return false; } else{ return searchWord(word.substring(1),childrens.get(ch)); } return false; } } class TrieNode { // Initialize your data structure here. public boolean leaf;//标识一个word到此结束 public Map<Character,TrieNode> childrens = new HashMap<Character,TrieNode>(); public TrieNode() { } }
居然报超时。
继续将类似于如下的代码借用中间变量提取出来,以避免求取多次。
if(ch=='.'){ for(Character c:childrens.keySet()){ if(searchWord(word.substring(1),childrens.get(c))){ return true; } } }
完整代码如下:
public class WordDictionary { // Adds a word into the data structure. private TrieNode root = new TrieNode(); public void addWord(String word) { Map<Character,TrieNode> childrens = root.childrens; for(int i=0;i<word.length();i++){ Character ch =word.charAt(i); TrieNode t = null; if(childrens.containsKey(ch)){ t = childrens.get(ch); } else{//此字符是一个新的分支 t = new TrieNode(); childrens.put(ch, t); } //继续寻找或插入第二个字符 childrens = t.childrens; //设置单词的标识 if(i==word.length()-1){ t.leaf = 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 searchWord(word,root); } public boolean searchWord(String word,TrieNode node) { if(word==null||node ==null){ return false; } if(word.length()==0){ return node.leaf; } Map<Character,TrieNode> childrens = node.childrens; Character ch =word.charAt(0); if(ch=='.'){ Set<Character> set = childrens.keySet(); String str = word.substring(1); for(Character c:set){ if(searchWord(str,childrens.get(c))){ return true; } } } else if(!childrens.containsKey(ch)){ return false; } else { return searchWord(word.substring(1),childrens.get(ch)); } return false; } } class TrieNode { // Initialize your data structure here. public boolean leaf;//标识一个word到此结束 public Map<Character,TrieNode> childrens = new HashMap<Character,TrieNode>(); public TrieNode() { } }
这样就AC 了,这个题真心不容易。
- LeetCode 211 - Add and Search Word - Data structure design
- LeetCode Add and Search Word - Data structure design
- Leetcode Add and Search Word - Data structure design
- leetcode:Add and Search Word - Data structure design
- [leetcode]Add and Search Word - Data structure design
- [LeetCode] Add and Search Word - Data structure design
- leetcode #211 Add and Search Word - Data structure design
- leetcode Add and Search Word - Data structure design
- [LeetCode]Add and Search Word - Data structure design,解题报告
- leetcode 211: Add and Search Word - Data structure design
- [Leetcode]Add and Search Word - Data structure design
- LeetCode Add and Search Word - Data structure design
- Leetcode: Add and Search Word - Data structure design
- [leetcode] Add and Search Word - Data structure design
- Leetcode: Add and Search Word - Data structure design (Java)
- leetcode Add and Search Word - Data structure design
- [leetcode] Add and Search Word - Data structure design
- leetcode--Add and Search Word - Data structure design
- 安卓手册 第一章(环境配置)
- vs2013下安装VA_X_Setup2048
- iOS 后台挂起程序
- Handler经典使用方法中的内存泄漏问题的解决方案
- CodeForces 342C--矩形盒子能最多放多少个球
- 《leetCode》:Add and Search Word - Data structure design
- JS模块化编程之AMD规范(一)
- HDU 2516 取石子游戏(博弈)
- 设计模式之五 --- 代理(Proxy)模式
- redis 缓存
- Android初探自定义View
- Android简易实战教程--第五话《开发一键锁屏应用》
- 欧几里德算法的证明
- SQl inner join,left join,right join