【LeetCode】49. 字母异位词分组

leetcode

 

解题思路:字母异位词分组

字母异位词(Anagram)指字母相同但排列顺序不同的字符串(如 "eat" 和 "tea")。核心思路是通过​​标准化处理​​将异位词映射到相同标识,再通过​​哈希表​​分组存储。以下是两种主流方法:

方法一:排序+哈希表(推荐)

  1. ​​标准化处理​​:对每个字符串按字母排序(异位词排序后相同)
  2. ​​哈希映射​​:以排序后的字符串为键,原始字符串列表为值
  3. ​​结果收集​​:提取哈希表所有值作为分组结果

方法二:计数+哈希表

  1. ​​标准化处理​​:统计字符串中每个字母出现次数(如 a3b2c1
  2. ​​哈希映射​​:以计数字符串为键分组
  3. ​​结果收集​​:同方法一

⚠️ 方法二虽时间复杂度更低,但实现较复杂;方法一更直观通用。


代码实现(方法一)

func groupAnagrams(strs []string) [][]string {
    // 创建哈希表: 键=排序后字符串,值=原始字符串列表
    groups := make(map[string][]string)

    for _, str := range strs {
        // 1. 字符串转字符切片
        chars := strings.Split(str, "")

        // 2. 对字符切片进行排序(标准化)
        sort.Strings(chars)

        // 3. 生成排序后的键
        key := strings.Join(chars, "")

        // 4. 将原始字符串加入对应分组
        groups[key] = append(groups[key], str)
    }

    // 5. 收集结果
    result := make([][]string, 0, len(groups))
    for _, group := range groups {
        result = append(result, group)
    }

    return result
}

关键代码注释

  1. ​​strings.Split(str, "")​​
    将字符串拆分为字符切片(如 "eat" → ["e","a","t"]
  2. ​​sort.Strings(chars)​​
    对字符切片按字典序排序(异位词排序后相同)
  3. ​​strings.Join(chars, "")​​
    将排序后的字符切片合并为字符串作为哈希表键
  4. ​​groups[key] = append(...)​​
    将原始字符串添加到对应分组(自动处理新键创建)
  5. ​​make([][]string, 0, len(groups))​​
    预分配结果切片内存(优化性能)

复杂度分析

指标方法一(排序)方法二(计数)
​​时间复杂度​​ O(n·k·logk) O(n·k)
​​空间复杂度​​ O(n·k) O(n·(k + |Σ|))
​​优势​​ 实现简单,通用性强 性能更高
​​局限​​ 排序耗时 代码复杂,需处理计数

其中:

  • n = 字符串数量
  • k = 字符串最大长度
  • |Σ| = 字符集大小(本题为26个小写字母)

运行示例

func main() {
    // 测试用例
    cases := [][]string{
        {"eat", "tea", "tan", "ate", "nat", "bat"}, // 标准输入
        {""},  // 空字符串
        {"a"}, // 单字符
    }

    for _, strs := range cases {
        fmt.Printf("输入: %v\n输出: %v\n\n", strs, groupAnagrams(strs))
    }
}
输入: [eat tea tan ate nat bat]
输出: [[ate eat tea] [nat tan] [bat]]

输入: []
输出: [[]]

输入: [a]
输出: [[a]]
 

边界测试说明

  1. ​​空字符串​​:[""] → [[""]](哈希表处理空键)
  2. ​​单字符​​:["a"] → [["a"]](无需排序直接分组)
  3. ​​全相同异位词​​:["abc","cba","bac"] → 单分组 [["abc","cba","bac"]]

优化扩展

    1. ​​计数法替代排序​​
      用长度26的数组统计字母频率,生成计数字符串(如 a1b2)作为键:
      func getCountKey(s string) string {
          count := [26]int{}
          for _, c := range s {
              count[c-'a']++
          }
          return fmt.Sprint(count) // 数组转字符串
      }
       
    2. ​​内存优化​​
      预分配结果切片容量:make([][]string, 0, len(groups))
posted @ 2025-05-30 16:05  云隙之间  阅读(85)  评论(0)    收藏  举报