LeetCode 热题 100 算法题解 - 49. 字母异位词分组

算法题解:字母异位词分组

问题描述

给定一个字符串数组 strs,我们需要将其中所有字母异位词组合在一起。字母异位词是指由相同字母重新排列形成的不同单词。最终可以按任意顺序返回结果列表。

示例

示例 1:

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

示例 2:

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

示例 3:

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

提示

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

解题思路

方法一:排序 + 哈希表

核心思想:字母异位词排序后的字符串是相同的,可以利用这一点作为哈希表的键来分组。

步骤

  1. 排序字符串:对每个字符串进行排序,排序后的字符串作为哈希表的键。
  2. 分组存储:将原始字符串存储到对应键的列表中。
  3. 返回结果:哈希表中所有值组成的列表即为最终结果。

复杂度分析

  • 时间复杂度:O(nk log k),其中 n 是字符串数量,k 是字符串平均长度。排序每个字符串需要 O(k log k) 时间。
  • 空间复杂度:O(nk),需要存储所有字符串。

方法二:计数 + 哈希表

核心思想:由于字符串仅包含小写字母,可以用一个长度为 26 的数组统计每个字母出现的次数,将计数数组转换为字符串作为哈希表的键。

步骤

  1. 统计字母频率:对每个字符串统计各字母出现次数。
  2. 生成键:将计数数组转换为特定格式的字符串(如用 # 分隔的数字)作为键。
  3. 分组存储:将原始字符串存储到对应键的列表中。
  4. 返回结果:哈希表中所有值组成的列表即为最终结果。

复杂度分析

  • 时间复杂度:O(nk),统计字母频率需要 O(k) 时间。
  • 空间复杂度:O(nk),需要存储所有字符串和计数键。

代码实现

方法一实现

from collections import defaultdict

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        groups = defaultdict(list)
        for s in strs:
            key = ''.join(sorted(s))
            groups[key].append(s)
        return list(groups.values())

代码解释

  1. 初始化哈希表:使用 defaultdict 创建值为列表的字典。
  2. 排序字符串:对每个字符串排序后作为键。
  3. 分组存储:将原始字符串添加到对应键的列表中。
  4. 返回结果:将哈希表的所有值转换为列表返回。

方法二实现

from collections import defaultdict

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        groups = defaultdict(list)
        for s in strs:
            count = [0] * 26
            for c in s:
                count[ord(c) - ord('a')] += 1
            key = '#'.join(map(str, count))
            groups[key].append(s)
        return list(groups.values())

代码解释

  1. 初始化哈希表:同样使用 defaultdict
  2. 统计字母频率:创建长度为 26 的数组统计每个字母出现次数。
  3. 生成键:将计数数组转换为用 # 分隔的字符串作为键。
  4. 分组存储:将原始字符串添加到对应键的列表中。
  5. 返回结果:将哈希表的所有值转换为列表返回。

方法比较

方法时间复杂度空间复杂度适用场景
排序+哈希表O(nk log k)O(nk)字符串长度较小
计数+哈希表O(nk)O(nk)字符串长度较大

总结

两种方法都能有效解决问题:

  • 方法一实现更简单,适合字符串长度较小的情况。
  • 方法二在理论上更高效,适合字符串长度较大的场景。

掌握这两种方法有助于应对不同约束条件下的类似问题。在实际应用中,可以根据具体需求选择最合适的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值