Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
首先理解一下题,什么是anagrams,就是,在String1里出现过的字符在String2里也都出现过,并且个数是一样的。
比如 “dog” , “gdo”是,更显示的是,“dog”的全排列都是anagrams。并且此题并不是真正的groups,比如输入{“dog”,“god”,“dgo”},应该的输出也是{“dog”,“god”,“dgo”}。理解的差不多就可以了。
解题思路:因为涉及到快速查找,很显然要用哈希。关键问题就是怎么用哈希,快速定位。
我的哈希是:
Map<String,List<String>> resMap = new HashMap<String,List<String>>();先讲解key的实现,根据题意怎么才能把是一个anagram的映射到同一个key上,这是本题的解题关键。很显然,如果把每个字符串排序当做key,value是排序前的,也是可以的。
我的实现是这样的,从a到z计算每个 字符出现的次数,没有出现的就不用管了。具体代码如下:
private String getKey(String s) { StringBuilder sb = new StringBuilder(); char[] chars = s.toCharArray(); int[] table = new int[26]; for (int i = 0; i < chars.length; i++) { table[chars[i]-'a']++; } for (int i = 0; i < 26; i++) { if (table[i] > 0) { sb.append((char)(i+'a')).append(table[i]); } } return sb.toString(); }这样应该比排序的方法要快吧!!!所以,本题的解法就呈现出来了,如下:
public List<String> anagrams(String[] strs) { List<String> res = new ArrayList<String>(); if (strs.length==0 || strs.length==1) return res; Map<String,List<String>> resMap = new HashMap<String,List<String>>(); List<String> keyList = new ArrayList<String>(); for (int i = 0; i < strs.length; i++){ String key = getKey(strs[i]); if (resMap.containsKey(key)) { resMap.get(key).add(strs[i]); } else { List<String> list = new ArrayList<String>(); list.add(strs[i]); resMap.put(key,list); keyList.add(key); } } for (int i = 0; i < keyList.size();i++){ List<String> list = resMap.get(keyList.get(i)); if (list.size() > 1) { res.addAll(list); } } return res; }