LeetCode100 49. 字母异位词分组

原题:

排序作为 key

两个字母异位词的组成完全相同 -> 排序后完全相同

复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        for (String s : strs) {
            char[] chars = s.toCharArray();
            // 对字符数组排序:异位词排序后字符序列必然相同
            Arrays.sort(chars);
            // 转回字符串,作为哈希表的 key
            String key = new String(chars);

            // 如果 key 不存在,就新建一个空 ArrayList;然后取出该分组列表
            // 把当前原始字符串 s 加入对应分组
            // if (!map.containsKey(key)) map.put(key, new ArrayList<>());
            // map.get(key).add(s);
            map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
        }
        //包装成 ArrayList 返回
        return new ArrayList<>(map.values());
    }
}

时间:O (n・k log k)

空间:O (n・k)

更优雅一点的解法

异位词的特征是「每个字母出现的次数相同」。

所以用一个长度为 26 的计数数组描述它:

复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] count = new char[26];
            for (int i = 0; i < str.length(); i++) {
                count[str.charAt(i) - 'a']++;
            }
            String key = new String(count);
            //if (!map.containsKey(key)) {
            //map.put(key, new ArrayList<>());
            //}
            //map.get(key).add(str);
            // key 第一次出现,新建空列表放进去
            // 取出该分组列表,加入当前字符串
            map.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
        }
        return new ArrayList<>(map.values());
    }
}

时间:O(n · k)

空间:O(n · k)

拓展

数据小可以用质数法

把每一个字符对应一个质数 质数乘积当成 key

不同字母组合的乘积必然不同,异位词的乘积必然相同。

这题用这个会爆

但是可以改成大数来存

复制代码
import java.math.BigInteger;
class Solution {

    private static final int[] PRIMES = {
        2, 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
    };

    public List<List<String>> groupAnagrams(String[] strs) {
        Map<BigInteger, List<String>> map = new HashMap<>();
        for (String s : strs) {
            BigInteger key = BigInteger.ONE;
            for (int i = 0; i < s.length(); i++) {
                int index = s.charAt(i) - 'a';
                key = key.multiply(BigInteger.valueOf(PRIMES[index]));
            }
            map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
        }
        return new ArrayList<>(map.values());
    }
}

这里觉得没有必要 还慢 内存也大

相关推荐
YFJ_mily1 小时前
第二届区块链技术与基础模型国际学术会议(BTFM2027)
算法·区块链·能源·智能系统·rdlink研发家·机器人自动化
汤姆宝库2 小时前
收官深拆:第一性原理、产业电网与未来推演
大数据·人工智能·算法
划破黑暗的第一缕曙光2 小时前
[C++]:5.STL:string(2)
java·c++·redis
hhhjhl2 小时前
Undici 跨端三方库仓颉适配全流程
java·开发语言·ubuntu
wangchunyu1142 小时前
JAVA JVM内存结构与运行时数据区
java·开发语言·jvm
光锥智能3 小时前
海康机器人举行2026移动机器人新品发布会:箱式存拣升级,「明智」系列发布
java·前端·机器人
行思理3 小时前
Nginx 跨站请求(CORS)配置完全指南:从原理到生产实践
java·前端·nginx
小溪学编程3 小时前
Spring @Bean 与 @Component 注解的区别详解
java·后端·spring