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;
    }

	
}