字母异位词分组(49. 字母异位词分组 && 剑指 Offer II 033. 变位词组)

题目:

思路:

【1】首先遍历是必不可少的,其次Map的辅助空间也是要用的,那么剩下的便是将字符串转成字符数组,然后排序,再转回字符串,用相同字符串作为key存于Map中,便可以是一组数据,然后遍历Map返回,时间复杂度为O(N*Nlog(N))

【2】换一种思路,字符源于ASCLL码,本质上是有容量限制的,基于题目限制了是小写字符,那么可以考虑用容量为26的数组,遍历一次,记录个数,再将数组转化一下作为key便可以达到和上面一样的效果。将Nlog(N)变为了N。

【3】又基于上面的思路其实还可以用进制的思想,去掉上面的辅助空间,也不用转化了,采用字符*26的形式,累乘便可以得到key,需要处理的就是在数值范围里面会变成0的情况,其次还要处理4*26*26*26 = 8*26*13*26,这种情况,所以又要加上额外的数值进行处理即可。

代码展示:

简单的第一版:

//执行用时:9 ms, 在所有 Java 提交中击败了32.04%的用户
//内存消耗:44.8 MB, 在所有 Java 提交中击败了26.05%的用户
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> result = new ArrayList<>();
        HashMap<String, List<String>> stringListHashMap = new HashMap<>();
        for (int i = 0; i < strs.length; i++){
            String temp = strs[i];
            char[] chars = temp.toCharArray();
            Arrays.sort(chars);
            temp = Arrays.toString(chars);
            List<String> arr = stringListHashMap.get(temp);
            if (arr == null){
                ArrayList<String> arrayList = new ArrayList<>();
                arrayList.add(strs[i]);
                stringListHashMap.put(temp,arrayList);
            }else {
                arr.add(strs[i]);
            }
        }
        for (List<String> value:stringListHashMap.values()){
            result.add(value);
        }
        return result;
    }
}

将第一版的繁琐代码简化:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, List<String>> hashMap = new HashMap<>();
        String temp;
        for (String str: strs){
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            temp = Arrays.toString(chars);
            List<String> arr = hashMap.getOrDefault(temp,new ArrayList<String>());
            arr.add(str);
            hashMap.put(temp,arr);
        }

        return new ArrayList<List<String>>(hashMap.values());
    }
}

优化版本:

//执行用时:5 ms, 在所有 Java 提交中击败了98.92%的用户
//内存消耗:44.8 MB, 在所有 Java 提交中击败了28.05%的用户
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, List<String>> hashMap = new HashMap<>();
        String temp;
        for (String str: strs){
            char[] ch = new char[26];
            for (char c : str.toCharArray()){
                ch[c-'a']++;
            }
            temp = String.valueOf(ch);
            List<String> arr = hashMap.getOrDefault(temp,new ArrayList<String>());
            arr.add(str);
            hashMap.put(temp,arr);
        }

        return new ArrayList<List<String>>(hashMap.values());
    }
}

最优解:

//执行用时:4 ms, 在所有 Java 提交中击败了99.94%的用户
//内存消耗:44.6 MB, 在所有 Java 提交中击败了43.26%的用户
class Solution {
    /**
     * 利用质数的概念
     * 利用数值相乘来作为键值区别两个字符串的不同
     * @param strs
     * @return
     */
    int[] prime = new int[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97, 101 , 103 ,107 , 109 ,113};
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<Long, List<String>> hashMap = new HashMap<>();
        long temp;
        for (String str: strs){
            temp = 1;
            for (char c : str.toCharArray()){
                // 其实核心是这里面的逻辑
                // 1) temp *= (c * 26 + 1); 与 2)temp *= prime[c - 'a']; 本质上是没有区别的
                // 为什么呢,2中你用质数,确保每个数值不相同 ,单1中你每加一个字符我都会*26代表多一个字符啊
                // 所以本质上都是可行的,至于为什么 c * 26 + 1 ,其实就是和 prime 不能用 1和2是一个道理
                // 用 1 ,无限a的结果和单个a的结果一样都是1区分不开 ,
                // 而prime 不能用 2 的理由 和 c * 26 + 1 为什么要加 1 一样
                // 为了防止 long 类型溢出的某种情况会转变为 0 ,如果long大到一定程度会变为 4611686018427387904L;
                // 而此时无论是乘以 2 ,4 ,8 这种只要才分开没有奇数因子的都会变为 0 ,多么搞事的东西,会让逻辑变得不正常
                // 所以为了避免为0 才需要 + 1
                temp *= (c * 26 + 1);
//                temp *= prime[c - 'a'];
            }
            List<String> arr = hashMap.getOrDefault(temp,new ArrayList<String>());
            arr.add(str);
            hashMap.put(temp,arr);
        }

        return new ArrayList<List<String>>(hashMap.values());
    }
}

 

posted @ 2023-08-03 17:28  忧愁的chafry  阅读(30)  评论(0编辑  收藏  举报