049.字母异位词分组
作者:沉默王二
发布时间:2024-09-20T09:59:45.371+0800
鲁迅曾逼逼:老虎说草原是绿色的,驴子说草原是蓝色的,两人争论不休,于是就找到狮子法官理论,结果狮子判老虎禁闭三天好好反思一下,因为他把时间浪费在了一件毫无意义的事情上。这件事的寓意其实很朴素,不要争论,如果别人觉得自己是对的,那你就对对对三连。把时间真正用到有意义的事情上,比如刷二哥的 LeetCode 题解。
题意
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
难度
中等
示例
示例 1:
textjavascripttypescriptcsshtmlbashjsonmarkdownpythonjavaccpprubygorustphpsqlyaml Copy
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
textjavascripttypescriptcsshtmlbashjsonmarkdownpythonjavaccpprubygorustphpsqlyaml Copy
输入: strs = [""]
输出: [[""]]
示例 3:
textjavascripttypescriptcsshtmlbashjsonmarkdownpythonjavaccpprubygorustphpsqlyaml Copy
输入: strs = ["a"]
输出: [["a"]]
### 分析
这道题的重点是理解什么是字母异位词,简单点说,就是每个字母出的次数都一样的字符串。
也就是说,如果两个字符互为 字母异位词,那么分别对它们进行排序后,必然是两个相同的字符串。
我们可以借助这一特性,将每个字符串按照字符排序后作为哈希表的键,然后将相同键的字符串归为一组。
如果看过 HashMap 的源码 ,其实就能找到类似的感觉,哈希相同的时候会使用拉链法将 key 相同的归为一组,放在链表中。
初始化一个哈希表 map,其中键是排序后的字符串,值是对应的异位词列表(ArrayList )。
遍历输入数组中的每一个字符串,对字符串中的字符进行排序,然后将排序后的字符串作为键,将原始字符串添加到该键对应的列表中。
遍历完成后,哈希表中的每个键对应的值就是一个字母异位词组。
返回哈希表中的所有值(即字母异位词分组)。
来看题解:
textjavascripttypescriptcsshtmlbashjsonmarkdownpythonjavaccpprubygorustphpsqlyaml Copy
import java.util.*;
public class Solution {
public List<List
// 创建哈希表,键是排序后的字符串,值是异位词列表
Map<String, List
// 遍历每一个字符串
for (String str : strs) {
// 将字符串转换为字符数组并排序
char[] charArray = str.toCharArray();
Arrays.sort(charArray);
String sortedStr = new String(charArray); // 将排序后的字符数组转回字符串
// 将排序后的字符串作为键,原始字符串添加到对应的列表中
if (!map.containsKey(sortedStr)) {
map.put(sortedStr, new ArrayList<>());
}
map.get(sortedStr).add(str); // 添加异位词到列表中
}
// 返回哈希表中的所有值,即所有异位词分组
return new ArrayList<>(map.values());
}
public static void main(String[] args) {
Solution solution = new Solution();
String[] strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
List<List<String>> result = solution.groupAnagrams(strs);
System.out.println(result); // 输出 [["eat","tea","ate"], ["tan","nat"], ["bat"]]
}
}
其中 str.toCharArray() 可以将字符串转换为字符数组 ,Arrays.sort(charArray) 可以对字符数组进行排序 ,new String(charArray) 可以将字符数组重新转换为字符串。
map.containsKey(sortedStr) 可以判断哈希表中是否包含某个键,map.put(sortedStr, new ArrayList<>()) 可以将一个空的 ArrayList 添加到哈希表中,map.get(sortedStr).add(str) 可以将异位词添加到相同 key 的列表中。
map.values() 可以获取哈希表中的所有值,返回类型是 Collection,我们可以通过 new ArrayList<>(map.values()) 将其转换为 ArrayList。
整体题解的难度不大,主要是理解字母异位词的概念,以及如何利用哈希表来存储异位词分组。
假设输入为 strs = ["eat", "tea", "tan", "ate", "nat", "bat"],处理过程如下:
eat 排序后为 aet,创建一个键为 aet 的列表,加入 eat。
tea 排序后为 aet,aet 键已存在,将 tea 加入该列表。
tan 排序后为 ant,创建一个键为 ant 的列表,加入 tan。
ate 排序后为 aet,将 ate 加入 aet 列表。
nat 排序后为 ant,将 nat 加入 ant 列表。
bat 排序后为 abt,创建一个键为 abt 的列表,加入 bat。
好,来看一下题解效率,还不错,击败 98.63 的用户。
总结
Java 在刷题的时候,比很多原生的编程语言,如 C 和 C++ 要容易一些,因为 Java 的 JDK 封装了很多有用的类库,包括 HashMap、ArrayList、Arrays 等,这些类库可以帮助我们更快地完成题目。
前提条件是一定要掌握 Java 的这些基础类库,推荐阅读:
力扣链接:https://leetcode.cn/problems/group-anagrams/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
PDF 版本目前只针对二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 加入我们吧。
一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 6200 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!
语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu
这道题可以说完全重写了,给出 3 道大家完全都能掌握的题解(主要是理解字母异位词的意思,如何和 HashMap 进行关联)。
增加代码注释,这样大家更容易看懂并掌握题解;
增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;
增加手绘图,这样大家更容易理解解题思路;
增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;
增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;
图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。
另外,这一版本会作为 PDF 的终稿随后在星球进行发布。