这道题有两种解法,第一解法,很好理解,利用HashSet,时间复杂度O(n).
public String longestWord(String[] words) { Arrays.sort(words); Set<String> set = new HashSet<>(); String res = ""; for(String word: words){ if(word.length()==1 || set.contains(word.substring(0, word.length()-1))){ //如果word长度是1,或者hashset中已经存在把word最后一个字符去掉的字符,那么这个word就可以加入到hashset中 set.add(word); if(word.length()>res.length()){ //如果word的长度比res的长度长,那么这个word可以替代res res = word; }else if(word.length()== res.length() && word.compareTo(res)<0){//或者如果word的长度与res的长度相同,但是比res的字符排序小,那么也可以替代res res = word; } } } return res; }
第二解法,利用Trie,需要对Trie的操作比较熟练,时间复杂度也是O(n*m), n是数组长度,m是字符串长度。Trie是一个特殊的数据结构,用于存储字典,之后可以利用DFS或者BFS对Trie进行搜索。它的结构一般包括一个String, 一个Trie数组,数组长度是26,对应26个英文字母。再加public方法,比如insert,用来把单词加入Trie中。当一个单词的最后一个字母被insert到Tire中之后,最后一个字母那一层的String变量被设置为被insert的word,由此可知这个单词结束了。Insert一个单词到Trie中是一个字母一个字母,一层一层的insert,形成一个树状结构。
class Trie{ String word = ""; Trie[] links = new Trie[26]; public void insert(String str){ char[] cs = str.toCharArray(); Trie curr = this; for(int i=0;i<cs.length;i++){ int index = cs[i] - 'a'; if(curr.links[index]==null){ curr.links[index] = new Trie(); } curr = curr.links[index]; } curr.word = str; } } String res = ""; public String longestWord(String[] words) { Trie trie = new Trie(); for(String word: words){ trie.insert(word); } dfs(trie); return res; } private void dfs(Trie trie){ if(trie.word.length()> res.length()) res = trie.word; if(trie.word.length()== res.length() && trie.word.compareTo(res)<0) res = trie.word; for(int i = 0;i<trie.links.length;i++){ if(trie.links[i]!=null && trie.links[i].word.length()>0) dfs(trie.links[i]); } }