Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
For example:
Input: ["tea","and","ate","eat","den"]
Output: ["tea","ate","eat"]
Interface: vector<string>anagrams(vector<string>&strs);
A:
首先简单介绍一下Anagram(回文构词法)。Anagrams是指由颠倒字母顺序组成的单词,比如“dormitory”颠倒字母顺序会变成“dirty room”,“tea”会变成“eat”。
回文构词法有一个特点:单词里的字母的种类和数目没有改变,只是改变了字母的排列顺序。
看了别人这些方法 无论怎么做,都是为了构建hashmap 的key
假设有n个string,string 最长长度为k
如果用按照字母排序,时间复杂度o(nklogk)
另外两种方法,o(nk)
这道题目除了思路,还要注意对于iterator, collection, map 等 他们的相关方法使用
public class Solution {
public List<String> anagrams(String[] strs) {
if (strs == null) {
return null;
}
List<String> result = new ArrayList<String>();
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
for (int i = 0; i < strs.length; i++) {
if(!hm.containsKey(sortLetter(strs[i]))) {
hm.put(sortLetter(strs[i]), new ArrayList<String>());
}
hm.get(sortLetter(strs[i])).add(strs[i]);
}
// hm.values() 返回的是 a collection of the values in this map
// 对于collection 结构的数据,都有iterator() 方法
Iterator iter = hm.values().iterator();
while(iter.hasNext()) {
ArrayList<String> item = (ArrayList<String>)iter.next();
if(item.size()>1) {
result.addAll(item);
}
}
/* hm.values() 返回的是实现了collection 的一种数据类型叫 Values, 不可以被转化为arraylist
ArrayList<ArrayList<String>> aa = (ArrayList<ArrayList<String>>)hm.values();
for (int i = 0; i < aa.size(); i++) {
if (aa.get(i).size() > 1) {
result.addAll(aa.get(i));
}
}
*/
return result;
}
String sortLetter(String s) {
//不要忘记考虑空字符串
if (s == null || s.length() == 0) {
return s;
}
char[] charArr = s.toCharArray();
Arrays.sort(charArr);
String str = new String(charArr);//用到String 的构造函数
return str;
}
}
网上看到另外一人解法 http://huntfor.iteye.com/blog/2077967:
public List<String> anagrams(String[] strs) {
List<String> result = new ArrayList<String>();
Map<String,List<String>> map = new HashMap<String,List<String>>();
if(strs == null || strs.length == 1){
return result;
}
for(String s : strs){
String seq = getSequence(s);
if(map.containsKey(seq)){
map.get(seq).add(s);
}else{
List<String> list = new ArrayList<String>();
list.add(s);
map.put(seq, list);
}
}
for(Map.Entry<String, List<String>> entry : map.entrySet()){
if(entry.getValue().size() > 1){
for(String s : entry.getValue()){
result.add(s);
}
}
}
return result;
}
private String getSequence(String s){
if("".equals(s)){
return "";
}
int[] hash = new int[256];
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length(); i++){
hash[s.charAt(i)]++;
}
for(int i = 97; i < 123; i++){
if(hash[i] != 0){
sb.append((char)i).append(hash[i]);
}
}
return sb.toString();
}
第二次写出错的地方:
while (iter.hasNext()) {
ArrayList<String> items = (ArrayList<String>)iter.next();
//cannot addAll(iter.next()) directely
//res.addAll(iter.next());
//test case:[""], the output should be [ ]
if (items.size() > 1) {
res.addAll(items);
}
}
/**
* Copyright: NineChapter
* - Algorithm Course, Mock Interview, Interview Questions
* - More details on: http://www.ninechapter.com/
*/
public class Solution {
private int getHash(int[] count) {
int hash = 0;
int a = 378551;
int b = 63689;
for (int num : count) {
hash = hash * a + num;
a = a * b;
}
return hash;
}
public ArrayList<String> anagrams(String[] strs) {
ArrayList<String> result = new ArrayList<String>();
HashMap<Integer, ArrayList<String>> map = new HashMap<Integer, ArrayList<String>>();
for (String str : strs) {
int[] count = new int[26];
for (int i = 0; i < str.length(); i++) {
count[str.charAt(i) - 'a']++;
}
int hash = getHash(count);
if (!map.containsKey(hash)) {
map.put(hash, new ArrayList<String>());
}
map.get(hash).add(str);
}
for (ArrayList<String> tmp : map.values()) {
if (tmp.size() > 1) {
result.addAll(tmp);
}
}
return result;
}
}
方法挺简单就是建立一个int数组来记录一个字符在一个string里面出现的次数 然后对比int[]数组是否相等就好。 不过这里有几个注意点和小技巧。 int数组可以只设为26而不是256, 然后数组这样的Object类型没法直接用来做key首先要写一个函数把它的hash值转换为基本数据类型。 然后就是要存arraylist作为value,因为如果直接把string用来做value最后会少加一次anagrams进rs。用arraylist存只要size大于1 就可以addall.
public class Solution {
public List<String> anagrams(String[] strs) {
List<String> rs = new ArrayList<String>();
if (strs.length < 2) {
return rs;
}
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
for (String i : strs) {
int len = i.length();
int[] temp = new int[26];
for (int j = 0; j < len; j++) {
temp[i.charAt(j) - 'a']++;
}
String t = getString(temp);
if (!hm.containsKey(t)) {
hm.put(t, new ArrayList<String>());
}
hm.get(t).add(i);
}
for (ArrayList<String> i : hm.values()) {
if (i.size() > 1) {
rs.addAll(i);
}
}
return rs;
}
private String getString(int[] a) {
StringBuilder sb = new StringBuilder();
for (int i : a) {
sb.append(i);
}
return sb.toString();
}
}