题目:
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
解析:
本题要求将所有的字母异位词放在一起,我们问题的关键在于如何求两个或者多个字符串属于字母异位词。本文介绍两种方法,时间复杂度都很低,稍快的一种有一点缺陷,但是测试用例都通过了。
第一种方式是将这两个或者多个字符串中的字符排序,然后看排序后的字符串是不是相同的,如果是,那么就属于字母异位词,否则就不是。
第二种方式是利用了质数的性质,只有同样的几个质数相乘才能得到同样的乘积,我们创建了一个长度为26的质数数组,以字符串中每个字符与’a’的距离来将字符映射到不同的质数上,将一个字符串中的所有字符表示的质数相乘,就可以将最终的乘积作为判断两个或者多个字符串是否是字母异位词的条件。具体看代码。
另外:对于两种方法的时间复杂度,由于代码中只有判断字母异位词的方法不同,第一种方式需要排序,时间复杂度为nlog(n),第二种方法只需要一次遍历,时间复杂度为n,所以第二种方法时间复杂度更低。但是第二种方式是计算若干个质数的乘积,当字符串很长的时候,乘积有可能超出int的范围,此时需要用long来表示,更长的时候,此方法就不可行了,只能通过第一种方法了。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Solution_49 {
/**
* 时间复杂度:12ms,98.96%
* 空间复杂度:41.6 MB,98.42%
*/
public List<List<String>> groupAnagramsOne(String[] strs) {
List<List<String>> res = new ArrayList<>();
//字母异位词都有一个共同的本质,我们以他们共同的本质为key以一个存放他们的容器list为value构建hashMap
HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
for (String str : strs) {
char[] chars = str.toCharArray();
//在本方法中,我们以排序后的字符串作为字母异位词的“本质”
Arrays.sort(chars);
String strAfterSort = new String(chars);
if (hashMap.get(strAfterSort) == null) {
ArrayList<String> list = new ArrayList<>();
list.add(str);
hashMap.put(strAfterSort, list);
res.add(list);
} else {
hashMap.get(strAfterSort).add(str);
}
}
return res;
}
/**
* 时间复杂度:9ms,99.76%
* 空间复杂度:41.8 MB,98.19%
*/
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
//字母异位词都有一个共同的本质,我们以他们共同的本质为key以一个存放他们的容器list为value构建hashMap
HashMap<Integer, ArrayList<String>> hashMap = new HashMap<>();
int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103};
for (String str : strs) {
char[] chars = str.toCharArray();
//在本方法中,我们以字符串中每个字符的代表的质数的乘积作为字母异位词的“本质”
int key = 1;
for (char ch : chars) {
key *= prime[ch - 'a'];
}
if (hashMap.get(key) == null) {
ArrayList<String> list = new ArrayList<>();
list.add(str);
hashMap.put(key, list);
res.add(list);
} else {
hashMap.get(key).add(str);
}
}
return res;
}
}