ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

算法刷题记录 —— 字母异位词分组(Group Anagrams)

算法刷题记录 —— 字母异位词分组(Group Anagrams) 题目链接49. 字母异位词分组题目分析这道题刚看到的时候确实没什么头绪。现在回过头来理解核心思想其实非常简洁利用哈希表的键值对机制——同一个键只能对应一条记录。​对于ant、tna、tan这样的字母异位词它们有一个共同的特点排序之后的字符串完全相同都是ant。既然如此把排序后的字符串作为哈希表的 key具有相同字母构成的单词天然就会被归到同一个 key 下面value 则用一个ListString来收纳这一组的所有原单词。本质上这是一种归一化思路——给每个单词找一个规范形式形式相同的归为一组。排序法是最直观的归一化手段此外也可以用计数法统计每个字母出现次数来构建 key但排序法代码最简洁。实现实现一基础写法classSolution{publicListListStringgroupAnagrams(String[]strs){MapString,ListStringmapnewHashMap();for(Strings:strs){char[]charss.toCharArray();Arrays.sort(chars);StringkeynewString(chars);if(!map.containsKey(key)){map.put(key,newArrayList());}map.get(key).add(s);}returnnewArrayList(map.values());}}逻辑很直白遍历每个单词 → 排序得到 key → 如果 key 不存在就新建一个空列表 → 把原单词加进去。最后map.values()直接就是分组结果。容易踩的两个坑​char[]不能直接当 key。Java 中数组的equals和hashCode基于对象引用而非内容两个内容相同的char[]会被当成不同的 key。必须用new String(chars)转成字符串。List的变量作用域。手写时容易把list声明在if块里面外部拿不到。可以用map.get(key)直接在外部获取引用更安全也更简洁。实现二使用computeIfAbsent简化classSolution{publicListListStringgroupAnagrams(String[]strs){MapString,ListStringmnewHashMap();for(Strings:strs){char[]charss.toCharArray();Arrays.sort(chars);// computeIfAbsent如果 key 不在哈希表中则插入一个新的 ArrayListm.computeIfAbsent(newString(chars),_-newArrayList()).add(s);}returnnewArrayList(m.values());}}思路和实现一一模一样区别在于用computeIfAbsent一行替代了手动判断containsKeyputget三步操作。computeIfAbsent的行为如果 key 存在返回对应的 value如果 key 不存在执行 Lambda 创建新列表并放入 map再返回这个新列表。拿到列表引用后直接.add(s)即可。代码量大幅减少可读性也更好。关键点总结① 为什么排序后就能分组字母异位词的定义是字母相同、排列不同。排序抹平了排列差异——eat、tea、ate排序后全是aet。排序结果天然就是分组依据。②char[]转String不可省略这是 Java 初学者最容易忽略的细节。数组类型的equals和hashCode是继承自Object的比较的是内存地址两个内容完全相同的char[]在 HashMap 眼中是不同的 key。new String(chars)才是值语义的比较。③computeIfAbsentvs 手动判断方式代码行数可读性适用场景手动containsKeyputget多适合新手理解流程逻辑较复杂的初始化computeIfAbsent一行简洁优雅大多数场景推荐使用小结字母异位词分组是一道哈希表的经典应用题难度不高但很能考察对 HashMap 核心特性的理解。抓住归一化 → 分组这条主线无论用排序还是计数都能顺利解决。推荐先用基础写法把流程走通再尝试用computeIfAbsent优化两种写法都熟练掌握之后这类题目基本可以秒过。
返回列表