leetcode题解-49. Group Anagrams

来源:互联网 发布:h5挂机游戏源码 编辑:程序博客网 时间:2024/05/22 18:56

题目:Given an array of strings, group anagrams together.For example, given: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Return: [ [“ate”, “eat”,”tea”], [“nat”,”tan”], [“bat”] ]

思路1,使用前面的题目来判断两个字符串是否为anagrams,这样有两种做法,第一个是循环嵌套,判断字符串间关系,并把已经识别过的字符串记录下来,以免重复判断,代码入下:

    public static List<List<String>> groupAnagrams(String[] strs) {        List<List<String>> res = new ArrayList<List<String>>();        //存储已经识别过的字符串        Set<Integer> used = new HashSet<>();        for(int i=0; i<strs.length; i++){            if(used.contains(i))                continue;            List<String> ana = new ArrayList<>();            used.add(i);            ana.add(strs[i]);            for(int j=i+1; j<strs.length; j++){                if(used.contains(j))                    continue;                if(isAnagram1(strs[i], strs[j])){                    ana.add(strs[j]);                    used.add(j);                }            }            res.add(ana);        }        return res;    }

另外一个方法就是,使用hashMap来存储识别过得字符串,然后遍历,对数组中的每一个字符串都使用hashMap的键值进行匹配,这样的缺点是非常耗时。

public static List<List<String>> groupAnagrams2(String[] strs) {        List<List<String>> res = new ArrayList<List<String>>();        Map<String, List<String>> used = new HashMap<>();        for(int i=0; i<strs.length; i++){            boolean flag = false;            for(String ss : used.keySet()){                if(isAnagram1(strs[i], ss)){                    List<String> aa = used.get(ss);                    aa.add(strs[i]);                    used.put(ss, aa);                    flag = true;                    break;                }            }            if(flag == false){            List<String> aa = new ArrayList<>();            aa.add(strs[i]);            used.put(strs[i], aa);            }        }        for(String ss:used.keySet())            res.add(used.get(ss));        return res;    }

以上两种方法中的isAnagram1都是之前一个题目中写的效率最高函数。如下。但是发现最终提交结果时都显示超时。说明一开始这种借用之前题目成果的办法并不适用。痛定思痛,接下来想一想有什么改进办法。

public static boolean isAnagram1(String s, String t) {        if(s.length() != t.length())            return false;        int [] tmp = new int[26];        for(char c : s.toCharArray())            tmp[c-'a'] ++;        for(char c:t.toCharArray())            tmp[c-'a'] --;        for(int a:tmp)            if(a!=0)                return false;        return true;    }

首先按照方法二进行改进,对每个字符串进行遍历的时候,先对其进行排序然后将其作为键值保存到hashMap中,这样就可以省去麻烦的判断过程,而直接使用hashMap.containsKey方法来达到判断的效果。节省了很多循环的时间。但这样的改进带来的提升有限,只击败了15%的用户

    public List<List<String>> groupAnagrams3(String[] strs) {        if(strs==null || strs.length == 0){            return new ArrayList<List<String>>();        }        HashMap<String, List<String>> map = new HashMap<String, List<String>>();        //Arrays.sort(strs);        for (String s:strs) {            char[] ca = s.toCharArray();            Arrays.sort(ca);            String keyStr = String.valueOf(ca);            if(!map.containsKey(keyStr))                map.put(keyStr, new ArrayList<String>());            map.get(keyStr).add(s);        }        for(String key: map.keySet()) {            Collections.sort(map.get(key));        }        return new ArrayList<List<String>>(map.values());    }

最后,还有一种极为巧妙的方法,使用26个质数与字母一一对应相乘作为字符串的键值保存到hashMap中。这样就省去了字符串的排序等操作,而且这种方法省去了最后对hashMap遍历生成列表的过程也节省了很多时间。这种方法击败了99%的用户。

    public List<List<String>> groupAnagrams4(String[] strs) {        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};//最多10609个z        List<List<String>> res = new ArrayList<>();        HashMap<Integer, Integer> map = new HashMap<>();        for (String s : strs) {            int key = 1;            for (char c : s.toCharArray()) {                key *= prime[c - 'a'];            }            List<String> t;            if (map.containsKey(key)) {                t = res.get(map.get(key));            } else {                t = new ArrayList<>();                res.add(t);                map.put(key, res.size() - 1);            }            t.add(s);        }        return res;    }
0 0
原创粉丝点击