LeetCode-49. Group Anagrams

Given an array of strings, group anagrams together.

Example:

Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

Note:

  • All inputs will be in lowercase.
  • The order of your output does not matter.

针对每个字符串,和当前所有group的第一个字符串比较,字符串比较使用map,不是最优解。

 1 class Solution {
 2     public List<List<String>> groupAnagrams(String[] strs) {//my
 3         List<List<String>> re = new ArrayList<>();
 4         for (int i = 0; i < strs.length; i++) {
 5             if(0==i){
 6                 List<String> group = new ArrayList<>();
 7                 group.add(strs[0]);
 8                 re.add(group);
 9             }
10             else{
11                 int flag = 0;
12                 for (int j = 0; j < re.size(); j++) {
13                     if(isAnagram(strs[i],re.get(j).get(0))){
14                         re.get(j).add(strs[i]);
15                         flag= 1;
16                     }
17                 }
18                 if(0==flag){
19                     List<String> group = new ArrayList<>();
20                     group.add(strs[i]);
21                     re.add(group);
22                 }
23             }
24         }
25         return re;
26     }
27     private boolean isAnagram(String s, String t) {
28         if(null==s&&null==t){
29             return true;
30         }
31         if(null==s||null==t||s.length()!=t.length()){
32             return false;
33         }
34         Map<Character,Integer> map = new HashMap<>();
35         for (int i = 0; i < s.length(); i++) {
36             char c= s.charAt(i);
37             if(map.containsKey(c)){
38                 map.put(c,map.get(c)+1);
39             }
40             else{
41                 map.put(c,1);
42             }
43         }
44         for (int i = 0; i < t.length(); i++) {
45             char c= t.charAt(i);
46             if(map.containsKey(c)){
47                 map.put(c,map.get(c)-1);
48                 if(map.get(c)==0){
49                     map.remove(c);
50                 }
51             }
52             else{
53                 return false;
54             }
55         }
56         return true;
57     }
58 }

 

优解思路是为每个group,设置一个唯一的hashcode,即map的key,然后讲字符串映射为哈希值并判断,所以哈希函数的设计决定了算法的时间复杂度,字符串长度为k,字符串个数为n。

  • 排序,key为排序后的字符串,但时间复杂度最优为O(nklogk)
  • 拼接字符串,key为使用特殊字符分割的26个数字,每个数值表示当前字母出现的次数,如#2#1#0#0...#0表示aab,时间复杂度为O(nk)
  • 素数,key为一个整数,每个字母使用一个素数表示,key为每个字母所表示素数的乘积,如12=2*2*3表示aab,时间复杂度为O(nk)

问题的关键是找到一个较优的唯一映射关系。

 1 public List<List<String>> groupAnagrams(String[] strs) {//哈希 map mytip
 2         List<List<String>> re = new ArrayList<>();
 3         int[] prime={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103};//素数代表一个字母
 4         Map<Integer,Integer> map=new HashMap<>();
 5         for (int i = 0; i < strs.length; i++) {
 6             int code = 1;
 7             for (int j = 0; j < strs[i].length(); j++) {
 8                 code*=prime[strs[i].charAt(j)-'a'];
 9             }
10             if(map.containsKey(code)){
11                 re.get(map.get(code)).add(strs[i]);
12             }
13             else {
14                 List<String> group = new ArrayList<>();
15                 group.add(strs[i]);
16                 map.put(code,re.size());
17                 re.add(group);
18             }
19         }
20         return re;
21     }
22     

 

相关题

有效的字母异位词 LeetCode242 https://www.cnblogs.com/zhacai/p/10574647.html

进阶题

查找所有异位词 LeetCode438 https://www.cnblogs.com/zhacai/p/10596274.html

posted @ 2019-03-22 10:26  月半榨菜  阅读(136)  评论(0编辑  收藏  举报