初始化一个空的 HashMap map。
遍历字符串数组 strs。
对第一个字符串 "eat"执行: 将 "eat" 转换为字符数组 ['e', 'a', 't'] 对字符数组进行排序,
得到 ['a', 'e', 't']
使用排序后的字符数组创建 key "aet" 从 map 中获取 key 为 "aet" 的值,
由于不存在,因此创建一个新的空列表 list = [] 将 "eat" 添加到 list 中,
现在 list = ["eat"] 将 key 为 "aet",value 为 ["eat"] 的键值对存入 map
对第二个字符串 "tea" 执行类似操作: 字符数组为 ['t', 'e', 'a'],排序后为 ['a', 'e', 't'],
key 为 "aet" 从 map 中获取 key 为 "aet" 的值,存在,
为 ["eat"] 将 "tea" 添加到列表中,现在列表为 ["eat", "tea"]
将更新后的列表存入 map,key 为 "aet" 对其余字符串 "tan", "ate", "nat", "bat" 执行类似操作,
最终 map 为: key 为 "aet",value 为 ["eat", "tea", "ate"]
key 为 "ant",value 为 ["tan", "nat"]
key 为 "abt",value 为 ["bat"] 从 map 中获取所有 value,构造结果列表,
即 [ ["eat", "tea", "ate"], ["tan", "nat"], ["bat"] ] 可以看到,
通过将每个字符串排序作为 key,并存储字母异位词的字符串列表作为 value,
算法成功将字母异位词分组了。
这样的分组过程更加高效,避免了对每个字符串都进行两两比较的低效操作。
总结来说就是我们通过这种方式,把原本存在的一个字符串,进行相应的拆解这样的话原本的单词就变成了一个一个独立的字母,这样的话就方便我们进行相应的比较
方便由一个key遍历整个数组找到全部的value
方法一: 排序
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String,List<String>> map = new HashMap<String,List<String>>();
for(String str:strs){
char[] array = str.toCharArray();
Arrays.sort(array);
String key = new String(array);
List<String> list = map.getOrDefault(key,new ArrayList<String>());
list.add(str);
map.put(key,list);
}
return new ArrayList<List<String>>(map.values());
}
}
api的相关解释
Java 示例
在 Java 中,getOrDefault
方法是 Java 8 引入的 Map
接口的一部分,具有以下签名:
default V getOrDefault(Object key, V defaultValue)
-
参数:
key
:要获取其关联值的键。defaultValue
:如果映射中不包含指定的键,则返回的默认值。
-
返回值:
- 返回与指定键关联的值,如果映射不包含该键,则返回
defaultValue
。
- 返回与指定键关联的值,如果映射不包含该键,则返回
通过这个api的相关调用这样的话就可以使得原本和这个定义的顺序不同的数组列表进行一个相关的重新的建立
时间复杂度:O(nklogk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要遍历 n 个字符串,对于每个字符串,需要 O(klogk) 的时间进行排序以及 O(1) 的时间更新哈希表,因此总时间复杂度是 O(nklogk)。
空间复杂度:O(nk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。需要用哈希表存储全部字符串。
拓展方法
这段代码是用来将给定的字符串数组 strs
中的同字母异序词(anagrams)进行分组,并返回分组后的结果。
解释代码逻辑:
-
方法签名和返回类型:
java
public List<List<String>> groupAnagrams(String[] strs)
groupAnagrams
方法接收一个字符串数组strs
,返回一个List<List<String>>
类型的对象,即列表的列表,每个内部列表包含同一组的同字母异序词。
-
流操作和集合操作:
java
return new ArrayList<>(Arrays.stream(strs) .collect(Collectors.groupingBy(str -> { char[] array = str.toCharArray(); Arrays.sort(array); return new String(array); })).values());
Arrays.stream(strs)
将字符串数组strs
转换为一个流(Stream)。Collectors.groupingBy(...)
是一个收集器(Collector),用于按照给定的条件进行分组。在这里,使用了一个 lambda 表达式作为分组的条件:char[] array = str.toCharArray();
将字符串str
转换为字符数组。Arrays.sort(array);
对字符数组进行排序,这样相同字母异序词排序后会得到相同的结果。return new String(array);
将排序后的字符数组转换回字符串,作为分组的依据。
Collectors.groupingBy(...)
将流中的字符串按照排序后的结果进行分组,得到一个Map<String, List<String>>
,其中键是排序后的字符串,值是原始字符串的列表。.values()
取出Map
中的所有值,即List<List<String>>
类型,每个内部列表包含同一组的同字母异序词。
-
返回结果:
return new ArrayList<>(...)
将Map<String, List<String>>
中的所有值(即同字母异序词分组后的列表)转换为一个新的ArrayList<List<String>>
返回。
示例说明:
假设输入字符串数组 strs
为 ["eat", "tea", "tan", "ate", "nat", "bat"]
,则经过 groupAnagrams
方法处理后的结果如下:
java
[ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]
"ate"
,"eat"
,"tea"
是同一组的同字母异序词。"nat"
,"tan"
是同一组的同字母异序词。"bat"
是单独一组,因为它没有与其他字符串是同字母异序词。
这段代码利用了 Java 中的流操作和集合操作,通过字符数组排序后的字符串作为键来分组,实现了高效的同字母异序词分组功能。