题目描述
// 49. 字母异位词分组
// 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,
// 但排列不同的字符串。
题解
// 一开始会想到逐个字符比对,但是太低效率了。
// 既然会被分到一组的String都是组成字符相同的String,
// 那么这些组成字符相同的String,不管字符再怎么排列,
// 如果把所有字符排序,得到的排序String一定是相等的,
// 所以我们使用一个HashMap的key来保存这些排序好的String,对应的value来保存
// 需要被分到List<String>组的组号,拥有相同的排序String,说明其字符串属于同一个组。
// 把遍历到的String str排序好,在map中寻找是否存在这个key(排序后str),
// 如果存在这个key,就取出这个key对应的组号value,把str放进第value组中。
// 这样就实现了组成字符相同的String放到一个组中了。
//
// 构建答案保存字符串组List<List<String>> res,构建HashMap<String, Integer> map,
// 定义创建小组的分组索引index,初始化为0。for循环遍历strs中字符串str,
// 将str转为char[],排序后再恢复为字符串形式,得到排序后的str,记为key。
// 条件判断key是否在map的key中,不在的话直接存入<key, index>,表示以后凡是
// 排序str等于这个key的,index组。之后index累加1,用作下一个组的组号。
//
// 如果map中key已存在,说明str是属于第 map.get(key) 组的,把str存入
// res中第的 map.get(key) 组。循环结束,返回res。
//
// 注意:String排序,要使用Arrays.sort(),就需要把String转为char[],排序好
// 再转回String。有人会想,为什么不直接把char[]作为key?因为HashMap中
// containsKey函数判断key对象相等,使用的是Object类中的equals方法,实际是判断
// 地址相等,而我们每次创建char[] temp都在new新对象,已经不是同一个引用了,
// 系统会认为我们遍历的str转换出的所有char[]都是不相等的,map.containsKey(key)
// 永远是false,循环就会一直执行if,不执行else,这就出错了。
// 而String包装类中的equals被重写了,是判断内容相等,我们就是要判断key的内容
// 相等,所以还需要将char[] temp转为String key。
//
// 输入案例 ["eat", "tea", "tan", "ate", "nat", "bat"]
// HashMap最终的保存情况,{ ["aet", 0], ["ant", 1], ["abt", 2] }
// 执行用时:7 ms, 在所有 Java 提交中击败了96.01%的用户
// 内存消耗:41.4 MB, 在所有 Java 提交中击败了73.42%的用户
import java.util.HashMap;
import java.util.Arrays;
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
HashMap<String, Integer> map = new HashMap<>();
int index = 0;
for (String str : strs) {
char[] temp = str.toCharArray();
Arrays.sort(temp);
String key = String.valueOf(temp);
if (!map.containsKey(key)) {
map.put(key, index++);
List<String> combination = new ArrayList<>();
combination.add(str);
res.add(combination);
}
else { // map.containsKey(key)
res.get(map.get(key)).add(str);
}
}
return res;
}
}