Anagrams
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
Solution1
- 这道题是用来找到字符串数组中的所有由相同字符(个数也相同)构成的字符串,例如[“ate”,”and”,”dna”,”ddna”,”tea”,”eat”],则输出为[“ate”,”tea”,”eat”,”and”,”dna”].下面的解法思路是这样的:从字符串数组中的第一个字符串开始,往后寻找与第一个字符串为同构字符串的所有字符串,然后再从第二个字符串开始,同样寻找所有与第二个字符串为同构字符串的所有字符串。以此类推。时间复杂度为 O(N2∗K) ,其中N为字符串数组的大小,K为每个字符串的长度。空间复杂度为 O(K) 。代码如下:
public class Solution {
public List<String> anagrams(String[] strs) {
List<String> result = new ArrayList<String>();
for(int i=0;i<strs.length;i++){
if(strs[i].length()==0) continue;
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
for(int k=0;k<strs[i].length();k++){
char c = strs[i].charAt(k);
if(!map.containsKey(c)) map.put(c,0);
map.put(c,map.get(c)+1);
}
boolean flag = false;
for(int j=i+1;j<strs.length;j++){
if(strs[i].length()!=strs[j].length()) continue;
if(isAnagram(strs[j],new HashMap<Character,Integer>(map))){
flag = true;
result.add(strs[j]);
strs[j] = "";
}
}
if(flag) result.add(strs[i]);
}
return result;
}
public boolean isAnagram(String s, HashMap<Character,Integer> map){
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(!map.containsKey(c)) return false;
if(map.get(c)<=0) return false;
map.put(c,map.get(c)-1);
}
for(int num:map.values()) if(num!=0) return false;
return true;
}
}
- 线上提交超时错误
Solution2
- 解法一可行,但是时间复杂度太高,并且代码复杂。主要原因在于第一个for循环遍历的时候,第二个循环里所有的字符串都有重复的去遍历考察是否和前面的字符串为同构。另外,将每一个字符串都用一个HashMap来表示的方法确实比较费时。其实,对于同构字符串来说,有一个特点是当两个字符串排序后得到的字符串应该相同。并利用这个排序后的字符串作为hash表的key,则所有的同构应该都存在这个key下面。代码如下:
public class Solution {
public List<String> anagrams(String[] strs) {
List<String> result = new ArrayList<String>();
HashMap<String,List<String>> map = new HashMap<String,List<String>>();
for(int i=0;i<strs.length;i++){
char[] ca = strs[i].toCharArray();
Arrays.sort(ca);
String s = new String(ca);
if(!map.containsKey(s)) map.put(s,new ArrayList<String>());
map.get(s).add(strs[i]);
}
for(String s:map.keySet()) if(map.get(s).size()>1) result.addAll(map.get(s));
return result;
}
}
- 时间复杂度为 O(N∗K∗logK) ,这里的 K∗logK 主要在于对字符串排序那里,如果有兴趣优化的话,可以利用数组下标来进行排序,因为都是小写字母,所以可以用一个长度为256的数组来对字符串进行排序。这样时间复杂度会优化到 O(N∗K) 。
Solution3
- 这里给出一个只需要一次for循环的代码。这种方法比解法二更优。
public class Solution {
public List<String> anagrams(String[] strs) {
List<String> result = new ArrayList<String>();
HashMap<String,Integer> map = new HashMap<String,Integer>();
for(int i=0;i<strs.length;i++){
char[] ca = strs[i].toCharArray();
Arrays.sort(ca);
String s = new String(ca);
if(!map.containsKey(s)) map.put(s,i);
else if(map.get(s)==-1) result.add(strs[i]);
else{
result.add(strs[i]);
result.add(strs[map.get(s)]);
map.put(s,-1);
}
}
return result;
}
}