题目:
Given an array of strings, group anagrams together.
Example:
Input: ["eat", "tea", "tan", "ate", "nat", "bat"]
,
Output:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
这道题就是简单地把一个array of strings里的anagram给group到一个list里。看到anagram想到的第一个方法就是排序,本来以为会有更好的解法,没想到最naive的排序法应该算是最好的解法了吧。看了solution以后才想到,anagram的另一种解法是count,差点给忘了,本质上感觉这俩都一样。以后见着anagram就可以往这两个思路上面靠。
1. sorting,刚开始还想岔了,后来才发现可以直接建一个map,key是sorted后的string,value是排序后是这个key的string的a list of strings,直接遍历一通把它们一个个塞进去就好了。这里学到了java对string排序的方法。时间复杂度应该是O(nklogk),k是单个单词的长度,n是数组的长度。空间复杂度O(nk)。
Runtime: 6 ms, faster than 98.20% of Java online submissions for Group Anagrams.
Memory Usage: 42.2 MB, less than 91.45% of Java online submissions for Group Anagrams.
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (int i = 0; i < strs.length; i++) {
char[] chars = strs[i].toCharArray();
Arrays.sort(chars);
String sorted = new String(chars);
if (!map.containsKey(sorted)) {
map.put(sorted, new ArrayList<>());
}
map.get(sorted).add(strs[i]);
}
return new ArrayList<>(map.values());
}
}
2. counting,本质和sorting差不多,就是利用了anagram每个字母出现的次数相同这个规律。代码写起来也跟上面差不多,就是要count一下每个string里每个字母出现的次数,会比较麻烦,而且count次数用的这个array还不能直接用作hashmap的key,大概是因为这是个mutable object吧(这里还没有仔细研究,以后回来填坑),所以代码会复杂一点。但是这个count的时间复杂度只需要对单词长度进行遍历就好,所以整体时间复杂度比sorting优秀,是O(nk),空间复杂度也一样是O(nk)。(诶,不过不知道为啥lc上算出来的运行时间咋多了这么多)
Runtime: 18 ms, faster than 30.36% of Java online submissions for Group Anagrams.
Memory Usage: 44 MB, less than 43.36% of Java online submissions for Group Anagrams.
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (int i = 0; i < strs.length; i++) {
int[] count = new int[26];
for (char c : strs[i].toCharArray()) {
count[c - 'a']++;
}
String countStr = Arrays.toString(count);
if (!map.containsKey(countStr)) {
map.put(countStr, new ArrayList<>());
}
map.get(countStr).add(strs[i]);
}
return new ArrayList<>(map.values());
}
}
(才发现原来去年做过这道题……当时用的C++代码就不贴了,复制一下当时随心写的,就可以删去年那篇不走心的了:
普通地遍历整个数组,统计每个词中每个字符出现的频率,把频率变成一个string用来作为hashmap的key,把生成相同的频率string的词放在这个key的value vector里,最后取所有的vector作为答案。
本来以为上面的count计数法会比排序快,因为排序的复杂度更高,没想到出来的结果却是排序超级快但是计数超级慢,猜测可能是因为string operations速度比较慢?)