LeetCode 补拙笔记 日期:2026.06.07 题目:49. 字母异位词分组

LeetCode 补拙笔记

0. 前言

  • 日期:2026.06.07
  • 题目:49. 字母异位词分组
  • 难度:中等
  • 标签:字符串、哈希表、排序

1. 题目理解

问题描述 :

给定一个字符串数组,将字母异位词组合在一起。字母异位词指的是由相同字母以不同顺序排列而成的单词。

示例:

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

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

2. 解题思路

核心观察

  • 字母异位词的核心特征:字符相同,顺序不同。
  • 排序后,异位词会变成同一个字符串(如 eat 和 tea 排序后都是 aet),因此可以用排序后的字符串作为哈希表的键。

算法步骤

  1. 遍历所有字符串;
  2. 对每个字符串排序,生成唯一键;
  3. 以排序后的字符串为键,将原字符串加入哈希表对应的列表;
  4. 最后取出哈希表中所有的值,即为分组结果。

3. 代码实现

java 复制代码
package lc0_lc99.lc49;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        int index =0;
        List<List<String>> res = new ArrayList<>();
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < strs.length; i++) {
            String s = strs[i];
            int n = method1(s, map);
            if (n != -1) {
                res.get(n).add(s);
            }
            else {
                ArrayList<String > ss = new ArrayList<>();
                ss.add(s);
                res.add(ss);
                char[] chars = s.toCharArray();
                Arrays.sort(chars);
                String s1 = String.valueOf(chars);
                map.put(s1,index++);
            }
        }

        return res;
    }

    private int method1(String s, HashMap<String, Integer> map) {
        char[] chars = s.toCharArray();
        Arrays.sort(chars);
        String s1 = String.valueOf(chars);
        if (map.containsKey(s1)) {
            return map.get(s1);
        }
        return -1;
    }
}

4. 代码优化说明

java 复制代码
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
    // 使用匿名内部类继承AbstractList实现懒加载
    return new AbstractList<>() {
        List<List<String>> list = null;

        // 懒加载初始化方法,仅在首次访问时执行
        private void init() {
            if (list != null) {
                return;
            }
            Map<String, List<String>> map = new HashMap<>();
            for (String str : strs) {
                // 排序生成异位词的统一key
                char[] chars = str.toCharArray();
                Arrays.sort(chars);
                String key = new String(chars);
                // computeIfAbsent:key不存在时创建新列表,存在时直接返回列表
                map.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
            }
            list = new ArrayList<>(map.values());
        }

        // 重写get方法,访问前触发初始化
        @Override
        public List<String> get(int index) {
            init();
            return list.get(index);
        }

        // 重写size方法,访问前触发初始化
        @Override
        public int size() {
            init();
            return list.size();
        }
    };
}
}

5. 复杂度分析

  • 时间复杂度 :O(nklog⁡k)O(nk\log k)O(nklogk),其中 nnn 是字符串数量,kkk 是字符串平均长度。每个字符串排序的时间复杂度为 O(klog⁡k)O(k\log k)O(klogk)。
  • 空间复杂度 :O(nk)O(nk)O(nk),哈希表存储所有字符串,总空间为 nnn 个长度为 kkk 的字符串。

6. 总结

  • 核心:排序+哈希表,用排序后的字符串作为异位词的唯一标识。
  • 优化点:使用 computeIfAbsent 简化哈希表操作,减少分支判断;懒加载方式延迟初始化结果列表,提升性能。
  • 关键技巧:异位词分组的核心是找到一个稳定的键,排序是最直接的实现方式。
相关推荐
信奥卷王4 小时前
[GESP202609 六级] 分树规划
算法
夏幻灵4 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
qq_284274055 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
徐小黑ACG6 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
qq_284274056 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
Navigator_Z6 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛7 小时前
cpp学习笔记--常量指针
java·开发语言·算法
GPU实战笔记7 小时前
云端 GPU 训练的账户余额提醒:它能说明什么,不能说明什么?
深度学习·算法·成本管理·gpu云计算·云端训练
Titan20247 小时前
MySQL访问个人学习笔记
笔记·学习·mysql