字母异位词分组
⛅前言
大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!
精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。
博客主页💖:知识汲取者的博客
LeetCode热题100专栏🚀:LeetCode热题100
Gitee地址📁:知识汲取者 (aghp) - Gitee.com
Github地址📁:Chinafrfq · GitHub
题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激
🔒题目
原题链接:49. 字母异位词分组
🔑题解
-
解法一:暴力
暴力的思路很简单,先遍历一遍strs,得到所有不同类型的字母异位词的种类,将他们存储到一个map集合中,key就是这个异位词,然后value标记位索引(从0开始),方便后面list集合定位到不同的分组。唯一需要注意的就是要对 list 进行初始化,否则会出现NPE!一遍过的感觉就是爽(●ˇ∀ˇ●)
这里给对示例一进行代码运行过程的模拟:
import java.util.*; /** * @author ghp * @title 字母异位词分组 */ class Solution { public List<List<String>> groupAnagrams(String[] strs) { List<List<String>> ans = new ArrayList<>(10); // 获取strs中所有不同类型字母异位词 Map<String, Integer> map = new HashMap<>(16); int i = 0; for (String str : strs) { char[] chars = str.toCharArray(); Arrays.sort(chars); String tempStr = new String(chars); // 判断当前字符串是否重复,只有不重复在加入map中 if (!map.containsKey(tempStr)){ map.put(tempStr, i++); // 初始化list,防止后面出现NPE List<String> list = new ArrayList<>(10); ans.add(list); } } // 遍历strs,将不同字母异味词进行一个归类 for (int j = 0; j < strs.length; j++) { char[] chars = strs[j].toCharArray(); Arrays.sort(chars); String key = new String(chars); ans.get(map.get(key)).add(strs[j]); } return ans; } }
复杂度分析:
- 时间复杂度: O ( n ∗ m ∗ l o g m ) O(n*m*logm) O(n∗m∗logm),一遍for循环换的时间复杂度是 n n n,然后排序的时间复杂度是 m ∗ l o g m m*logm m∗logm
- 空间复杂度: O ( n ∗ m ) O(n*m) O(n∗m)
其中 n n n 为字符串数组的长度, m m m位字符串的最大长度
-
解法二:排序(这个是LeetCode官方提供的)
可以看到LeetCode官方提供的代码,和我写思路是类似的的。都是先对字符串进行排序,然后通过map的key不重复的特性来记录不同异位字母。相比较,官方代码最大的亮点就是使用了
getOrDefault
方法,该方法是Java8新增的,相较于传统的get
方法,不会发生NPE问题,所以不要像我之前写的那样,还要去初始化List,这样就能够很好的将两个for循环合并成一个,这样虽然时间复杂度没有降低,但是一定程度上也降低了时间损耗(经测试解法一耗时8ms,解法二耗时5ms)import java.util.*; /** * @author ghp * @title 字母异位词分组 */ class Solution { public List<List<String>> groupAnagrams(String[] strs) { Map<String, List<String>> map = new HashMap<>(); // 遍历strs,对异位字母进行分组 for (String str : strs) { // 对字符串按照字母顺序进行排序(自然顺序) char[] array = str.toCharArray(); Arrays.sort(array); String key = new String(array); // 获取对应key的value值,key不存在就返回默认值(也就是一个ArrayList对象) List<String> list = map.getOrDefault(key, new ArrayList<>()); list.add(str); map.put(key, list); } return new ArrayList<>(map.values()); } }
复杂度分析:
- 时间复杂度: O ( n ∗ m ∗ l o g m ) O(n*m*logm) O(n∗m∗logm),一遍for循环换的时间复杂度是 n n n,然后排序的时间复杂度是 m ∗ l o g m m*logm m∗logm
- 空间复杂度: O ( n ∗ m ) O(n*m) O(n∗m)
其中 n n n 为字符串数组的长度, m m m位字符串的最大长度