import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/*
* @lc app=leetcode.cn id=49 lang=java
*
* [49] 字母异位词分组
*
* https://leetcode-cn.com/problems/group-anagrams/description/
*
* algorithms
* Medium (58.55%)
* Likes: 199
* Dislikes: 0
* Total Accepted: 32.7K
* Total Submissions: 55.5K
* Testcase Example: '["eat","tea","tan","ate","nat","bat"]'
*
* 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
*
* 示例:
*
* 输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
* 输出:
* [
* ["ate","eat","tea"],
* ["nat","tan"],
* ["bat"]
* ]
*
* 说明:
*
*
* 所有输入均为小写字母。
* 不考虑答案输出的顺序。
*
*
*/
// @lc code=start
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// List<List<String>> res = new ArrayList<List<String>>();
HashMap<String,List> map = new HashMap<String,List>();
for (String str : strs) {
char[] key = str.toCharArray();
Arrays.sort(key);
// String k = String.valueof(key);
String k = new String(key);
//官解的代码太优雅了,if else可以简单提取公共部分和非公共部分,把非公共部分放入if中单独处理。如下面这段代码,公共部分就是要往map中某个key对应的List值中添加元素,有差异的地方是如果key不存在,可以先执行map.put(key,new ArrayList()),添加一个空的list作为对应key的值,代码就可以简化成两行。。。
// if( map.containsKey(k)){
// map.get(k).add(str);
// } else {
// List<String> list = new ArrayList<String>();
// list.add(str);
// map.put(k, list);
// }
// }
if( !map.containsKey(k)) map.put(k, new ArrayList());
map.get(k).add(str);
}
//map.value返回的是一个Collection,可以在新建ArrayList的时候直接用来初始化。
// for (String key : map.keySet()) {
// res.add(map.get(key));
// }
// return res;
return new ArrayList(map.values());
}
}
// @lc code=end
Leetcode官解中的按计数分类的代码,省去了将字符串排序的过程,对每个字符串仅记录26个字母出现的顺序。将时间复杂度由O(NKlogK)
减少为O(NK)
, 其中N为strs
的长度,K为strs
中最长的字符串的长度。
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
if (strs.length == 0) return new ArrayList();
Map<String, List> ans = new HashMap<String, List>();
int[] count = new int[26];
for (String s : strs) {
Arrays.fill(count, 0);
for (char c : s.toCharArray()) count[c - 'a']++;
//key为以#为分隔符分隔出每个字母出现的次数,包含26个#与26个数字,每个数字对应一个字母出现的次数,如字符串abbccc的key为#1#2#3#0#0.....#0一共有23个0。
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < 26; i++) {
sb.append('#');
sb.append(count[i]);
}
String key = sb.toString();
if (!ans.containsKey(key)) ans.put(key, new ArrayList());
ans.get(key).add(s);
}
return new ArrayList(ans.values());
}
}