HOT100 49.字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母


整体思路

字母异位词的字符重新排列后完全相同。例如,"eat" 和 "tea" 排序后都是 "aet"。我们可以利用这一特性:

  1. 排序后的字符串作为键 :将每个字符串排序后得到一个键。
  2. 哈希表分组 :用哈希表存储所有字符串,键是排序后的字符串,值是原始字符串的列表。

这样,所有字母异位词会被归到同一个键下,最终直接返回哈希表的值列表即可。

代码步骤分解

1. 初始化哈希表
Map<String, List<String>> map = new HashMap<>();
  • 作用 :创建一个哈希表,键是排序后的字符串,值是原始字符串的列表。
  • 关键点 HashMap<String, List<String>> 表示键是 String,值是 List<String> 类型。

2. 遍历每个字符串
for (String str : strs) {

// 处理每个字符串

}
  • 作用 :遍历输入的字符串数组 strs 中的每一个字符串 str
  • 语法 :这是 Java 的增强型 for 循环,等价于 for (int i = 0; i < strs.length; i++) { String str = strs[i]; ... }

3. 字符串转换为字符数组并排序
char[] array = str.toCharArray();

Arrays.sort(array);
  • 作用 :将字符串转为字符数组并排序。
  • 关键函数
    • str.toCharArray():将字符串转为 char[]。例如,"eat" → ['e', 'a', 't']
    • Arrays.sort(array):对字符数组排序。例如,['e','a','t']['a','e','t']

4. 生成哈希表的键
String key = new String(array);
  • 作用 :将排序后的字符数组转回字符串,作为哈希表的键。
  • 示例 :排序后的 ['a','e','t']"aet"
5. 更新哈希表
List<String> list = map.getOrDefault(key, new ArrayList<>());

list.add(str);

map.put(key, list);
  • 作用 :将当前字符串添加到对应的分组列表中。
  • 关键函数
    • map.getOrDefault(key, new ArrayList<>())
      • 如果键 key 存在,返回对应的列表。
      • 如果键不存在,返回一个空的 ArrayList
    • list.add(str):将当前字符串添加到列表。
    • map.put(key, list):将更新后的列表存回哈希表。

6. 返回结果
return new ArrayList<>(map.values());
  • 作用 :将哈希表中的所有值(分组列表)转换为一个 ArrayList
  • 关键点 map.values() 返回所有分组的列表集合,new ArrayList<>() 将其转为列表的列表。

示例模拟

输入:["eat", "tea", "tan", "ate", "nat", "bat"]

原始字符串

排序后的键

哈希表操作

"eat"

"aet"

添加到键 "aet" 的列表 → ["eat"]

"tea"

"aet"

添加到键 "aet" 的列表 → ["eat", "tea"]

"tan"

"ant"

添加到键 "ant" 的列表 → ["tan"]

"ate"

"aet"

添加到键 "aet" 的列表 → ["eat", "tea", "ate"]

"nat"

"ant"

添加到键 "ant" 的列表 → ["tan", "nat"]

"bat"

"abt"

添加到键 "abt" 的列表 → ["bat"]

最终结果:[["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]


关键函数总结

函数/语法

作用

示例

toCharArray()

字符串转字符数组

"eat" → ['e','a','t']

Arrays.sort()

对数组排序

['e','a','t'] → ['a','e','t']

new String(char[])

字符数组转字符串

['a','e','t'] → "aet"

map.getOrDefault()

安全获取键值,避免空指针

map.getOrDefault("aet", new ArrayList<>())

map.values()

获取哈希表中所有值的集合

返回所有分组的列表


时间复杂度分析

  • 排序时间 :每个字符串排序耗时 O(klogk),其中 k 是字符串长度。
  • 总时间复杂度 :O(n⋅klogk),其中 n 是字符串数量。
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());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值