题目
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明
所有输入均为小写字母。
不考虑答案输出的顺序。
思路
思路很简单,遍历输入中的每个词,判断它是否属于某一类已知的异位词,如果是,则和已知的异位词放入一个List,如果不是,则新建一个List放入。
异位词的判断:
(1)遇到一个词,我们先将其转换为char数组,然后进行排序再转回String类型,以此作为key值,我们维护一个保存不重复key值的HashMap容器,value则是一个List类型,用来放异位词。每当遍历到的key值不在容器中时,我们put一个key进去,反正我们将当前字符串add到对应的List里面。
(2)利用HaspMap统计字符串的词频,词频相同则为异位词,但这种容易超时。
代码1
public class problem49_2 {
public List<List<String>> groupAnagrams(String[] strs) {
//特判
if (strs.length == 0)
return new ArrayList();
Map<String, List> ans = new HashMap<String, List>();
for (String s : strs) {
char[] ca = s.toCharArray();
Arrays.sort(ca);
String key = String.valueOf(ca);
// String key = new String(ca);
if (!ans.containsKey(key))
ans.put(key, new ArrayList());
ans.get(key).add(s);
}
// System.out.println(ans.values().getClass().toString());
return new ArrayList(ans.values());
}
public static void main(String[] args) {
problem49_2 pro = new problem49_2();
String[] strs = { "eat", "tea", "tan", "ate", "nat", "bat" };
List<List<String>> res = pro.groupAnagrams(strs);
for (int i = 0; i < res.size(); i++) {
for (int j = 0; j < res.get(i).size(); j++) {
System.out.print(res.get(i).get(j) + " ");
}
System.out.println();
}
}
}
代码2
public class problem49 {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<List<String>>();
// 遍历每个字符串输出
for (int i = 0; i < strs.length; i++) {
//是否跳过当前外层循环标计
boolean jump = false;
for (int j = 0; j < res.size(); j++) {
// 判断当前字符串是否属于以及出现过的某一类异位词
// System.out.println(strs[i]+" "+res.get(j).get(0));
if (isEqual(strs[i], res.get(j).get(0))) {
res.get(j).add(strs[i]);
//跳过当前循环
jump = true;
break;
}
}
if (jump)
continue;
// 新的异位词新开一个List存放,并进行添加
res.add(new ArrayList<String>());
res.get(res.size() - 1).add(strs[i]);
}
return res;
}
// 判断两个字符串的组成是否相同
public boolean isEqual(String str1, String str2) {
if (str1.length() != str2.length())
return false;
HashMap<String, Integer> map = new HashMap<>();
// 统计str1各字母出现的频率
for (int i = 0; i < str1.length(); i++) {
if (map.containsKey(str1.charAt(i) + "")) {
int num = map.get(str1.charAt(i) + "");
map.put(str1.charAt(i) + "", num + 1);
} else {
map.put(str1.charAt(i) + "", 1);
}
}
// printhash(map);
// 根据str2出现的字母递减频率值
for (int i = 0; i < str2.length(); i++) {
if (map.containsKey(str2.charAt(i) + "")) {
int num = map.get(str2.charAt(i) + "");
map.put(str2.charAt(i) + "", num - 1);
// 若有频率递减为负,则返回false
if (num - 1 < 0)
return false;
} else {
// System.out.println("test");
return false;
}
}
return true;
}
// 打印hash便于调试
public void printhash(HashMap<String, Integer> map) {
for (Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key + "," + value);
}
}
public static void main(String[] args) {
problem49 pro = new problem49();
String[] strs = { "eat", "tea", "tan", "ate", "nat", "bat" };
List<List<String>> res = pro.groupAnagrams(strs);
for (int i = 0; i < res.size(); i++) {
for (int j = 0; j < res.get(i).size(); j++) {
System.out.print(res.get(i).get(j) + " ");
}
System.out.println();
}
// System.out.println(pro.isEqual("eat", "bat"));
}
}