Given an array of strings, group anagrams together.
For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"],
Return:
[ ["ate", "eat","tea"], ["nat","tan"], ["bat"] ]
Note: All inputs will be in lower-case.
这道题的意思是给定一个字符串数组,然后将相同字母组成的字符串放在一个List里面,最后返回结果。
第一次我的想法是,用数组res纪录每个List<String>中的String的长度,然后遍历数组,先对比已经记录的res数组中的数,如果相同,找到对应List中的String,然后对比这个String和strs[i],但是提交超时。
public class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> result = new ArrayList<List<String>>();
int len = strs.length;
int[] res = new int[len];
int ans = 0, flag = 0;
for (int i = 0; i < len; i++) {
flag = 0;
for (int j = 0; j < ans; j++) {
if (strs[i].length() == res[j]) {
if (equal(result.get(j).get(0), strs[i])) {
result.get(j).add(strs[i]);
flag = 1;
break;
}
}
}
if (flag == 1)
continue;
List<String> l1 = new ArrayList<String>();
l1.add(strs[i]);
result.add(l1);
res[ans] = strs[i].length();
ans++;
}
return result;
}
public boolean equal(String str1, String str2) {
int len = str1.length();
int[] ans = new int[len];
char[] Str1 = str1.toCharArray();
char[] Str2 = str2.toCharArray();
int flag = 0;
for (int i = 0; i < len; i++) {
flag = 0;
char ch = Str1[i];
for (int j = 0; j < len; j++) {
if (ch == Str2[j]) {
if (ans[j] == 0) {
ans[j] = 1;
flag = 1;
break;
}
}
}
if (flag == 0)
return false;
}
return true;
}
}
-------------- > 然后修改了res数组,将它改成了纪录每一个List中的String的每一个字母相加得到的数字。但是仍然超时,超时的字符串总共有10000个。
-------------- > 之后修改了res数组,将它改成一个hashMap<Integer,List<Integer>>记录的还是上述内容,ac了,但是时间还是比较长。
代码如下
public class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> result = new ArrayList<List<String>>();
Map<Integer,List<Integer>> sum = new HashMap<Integer,List<Integer>>();
int len = strs.length;
int flag = 0,len_str = 0,res_pos ,ans = 0;
for (int i = 0; i < len; i++) {
flag = 0;
len_str = 0;
for( int j =0;j<strs[i].length();j++)
len_str += strs[i].charAt(j);
if( sum.containsKey(len_str) ){
List<Integer> l1 = sum.get(len_str);
for( int pos = 0;pos<l1.size();pos++){
res_pos = l1.get(pos);
if (equal(result.get(res_pos).get(0), strs[i])) {
result.get(res_pos).add(strs[i]);
flag = 1;
break;
}
}
}
if (flag == 1)
continue;
List<String> l1 = new ArrayList<String>();
l1.add(strs[i]);
result.add(l1);
int num = 0;
for( int j = 0;j<strs[i].length();j++){
num += (int)strs[i].charAt(j);
}
if( sum.containsKey(num)){
List<Integer> l2 = sum.get(num);
l2.add(ans);
}else{
List<Integer> l2 = new ArrayList<Integer>();
l2.add(ans);
sum.put(num,l2);
}
ans++;
}
return result;
}
public boolean equal(String str1, String str2) {
int len = str1.length();
if( len != str2.length())
return false;
char[] Str1 = str1.toCharArray();
char[] Str2 = str2.toCharArray();
Arrays.sort(Str1);
Arrays.sort(Str2);
for( int i = 0; i<len;i++){
if( Str1[i] != Str2[i])
return false;
}
return true;
}
}
然后在这里发现一个细节:
对于判断两个字符串是否由相同数字组合的时候,第一次写的实际上要比第二次的快不少(虽然第一感觉应该是第二种快一些,因为第一种的最差情况要到n平方的时间复杂度)。
------- >然后发现这里特别慢的原因是hashmap<String,List<Integer>>这里需要建立很多次的List,但是result中又有很多的List<String>其实两者的数量是一样的,所以发现其实可以修改,不用纪录每个字符串相加的和,把每一个字符串(转换成char[]再转回去)排序就可以了,这次酒很快乐,并且代码也少了很多。
public class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> result = new ArrayList<List<String>>();
Map<String,List<String>> map = new HashMap<String,List<String>>();
int len = strs.length;
for( String s : strs){
char[] ss = s.toCharArray();
Arrays.sort(ss);
String sort = new String(ss);
if( map.containsKey(sort) ){
map.get(sort).add(s);
}else{
List<String> s2 = new ArrayList<String>();
s2.add(s);
map.put(sort, s2);
result.add(s2);
}
}
return result;
}
}