题目及测试
package pid049;
import java.util.List;
/*字谜分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["natt","tatn"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
*/
public class main {
public static void main(String[] args) {
String[][] testTable1 ={
{"eat", "tea", "tan", "ate", "nat", "bat"},
{"eatt", "ttea"},
{"erd", "tea"}
};
for(int i=0;i<testTable1.length;i++){
test(testTable1[i]);
}
}
private static void test(String[] ito) {
Solution solution = new Solution();
int length=ito.length;
for(int i=0;i<length;i++){
System.out.print( ito[i]+" ");
}
System.out.println();
long begin = System.currentTimeMillis();
List<List<String>> rtn=solution.groupAnagrams(ito);//执行程序
long end = System.currentTimeMillis();
for(int i=0;i<rtn.size();i++){
List<String> now=rtn.get(i);
for(int j=0;j<now.size();j++){
System.out.print( now.get(j)+" ");
}
System.out.println();
}
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,826ms,超慢)
建立一个hashmap的列表,每个hashmap 以character为key,以integer为value
把每个字符串,每个字符的数量存入其中
然后将hashmap的equals方法,逐个比对后加入
package pid049;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
int length=strs.length;
if(length==0){
return null;
}
List<HashMap<Character, Integer>> source=new ArrayList<>();
for(int i=0;i<length;i++){
HashMap<Character, Integer> now=new HashMap<>();
String nowStr=strs[i];
for(int j=0;j<nowStr.length();j++){
Character nowChar=nowStr.charAt(j);
if(now.containsKey(nowChar)){
now.put(nowChar, now.get(nowChar)+1);
}
else{
now.put(nowChar, 1);
}
}
source.add(now);
}
List<List<String>> result=new ArrayList<>();
List<String> sour=new ArrayList<>(Arrays.asList(strs));
boolean[] hasStr=new boolean[length];
for(int i=0;i<length;i++){
if(hasStr[i]==false){
List<String> nowResult=new ArrayList<>();
nowResult.add(strs[i]);//入字符串
hasStr[i]=true;
for(int j=i+1;j<length;j++){
if(hasStr[j]==false){
if(source.get(i).equals(source.get(j))){
nowResult.add(strs[j]);//入字符串
hasStr[j]=true;
}
}
}
result.add(nowResult);
}
}
return result;
}
}
解法2(成功,22ms,很快)
算法的关键是:如何将多个字母异位词定位到一个分类,即类似与hash(a)=hash(b)
这里的方法是,将字符串转为char数组,根据字母大小排序,再转为字符串,得到它的hashcode
建立一个hashmap<integer,integer>,key为字符串对应的hashcode,value为result里字符串对应的index
字符串最后加入index对应的那个list中去
public List<List<String>> groupAnagrams(String[] strs) {
HashMap<Integer, Integer> map=new HashMap<>();
List<List<String>> result=new ArrayList<>();
List<String> list;
for(String string:strs){
int hash=getAnagramHash(string);
int index=0;
if(map.containsKey(hash)){
index=map.get(hash);
}else{
list=new ArrayList<>();
result.add(list);
index=result.size()-1;
map.put(hash, index);
}
list=result.get(index);
list.add(string);
}
return result;
}
/** 先将string安装字母顺序排列,得到排序后字符串的hashcode
* @param string
* @return
*/
public int getAnagramHash(String string){
char[] chars=string.toCharArray();
Arrays.sort(chars);
return new String(chars).hashCode();
}
解法3
其他的解法,不同的地方在于hash的方法不一样。
一种是,char数组排序后,生成的字符串作为hash的结果(不对这个生成的字符串hashcode)。
另一种是,用int[26]统计字符串的字母的个数,用字符串 1#2#3... 作为hash的结果,其中的1就代表a的个数,其他类似