每日一题·字母异位词分组

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

示例 1:

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

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

解释:

  • 在 strs 中没有字符串可以通过重新排列来形成 "bat"
  • 字符串 "nat""tan" 是字母异位词,因为它们可以重新排列以形成彼此。
  • 字符串 "ate""eat""tea" 是字母异位词,因为它们可以重新排列以形成彼此。

示例 2:

输入: strs = [""]

输出:[[""]]

示例 3:

输入: strs = ["a"]

输出:[["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母
java 复制代码
public List<List<String>> groupAnagrams(String[] strs) {

      // 创建一个空字典
      Map<String, List<String>> map = new HashMap<>();

      // 遍历每个单词
      for (String s : strs) {

          // 第一步:把单词拆成字符数组
          // "eat" → ['e','a','t']
          char[] chars = s.toCharArray();

          // 第二步:对字符排序
          // ['e','a','t'] → ['a','e','t']
          Arrays.sort(chars);

          // 第三步:重新拼成字符串,作为key
          // ['a','e','t'] → "aet"
          String key = new String(chars);

          // 第四步:把原单词放入对应的分组
          // 如果字典里没有"aet"这个key,就新建一个空列表
          // 如果已经有了,就直接往里加
          map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
      }

      // 把字典里所有的value(每一组列表)收集起来返回
      return new ArrayList<>(map.values());
  }

1 List ------ 有序的"列表/数组"

可以把 List 理解成一个可以自由伸缩的数组。

普通数组长度固定:

String[] arr = new String[3]; // 只能放3个,满了就不能加了

List 长度可变:

List<String> list = new ArrayList<>();

list.add("eat"); // ["eat"]

list.add("tea"); // ["eat", "tea"]

list.add("ate"); // ["eat", "tea", "ate"]

List<String> 里的 <String> 表示这个列表只装字符串。

List<List<String>> 就是列表里面装列表,比如:

\["eat", "tea", "ate"\], // 第一组 \["tan", "nat"\], // 第二组 \["bat"\] // 第三组

2 Map ------ "字典/键值对"

Map 就像一本字典,每个"词(key)"对应一个"解释(value)"。

key → value

"aet" → ["eat", "tea", "ate"]

"ant" → ["tan", "nat"]

"abt" → ["bat"]

Map<String, List<String>> map = new HashMap<>();

// 存入数据

map.put("aet", someList);

// 取出数据

map.get("aet"); // 返回 ["eat", "tea", "ate"]

Map<String, List<String>> 表示:

  • key 是 String(排序后的字符串)

  • value 是 List<String>(同一组的单词列表)

3 Map 和 HashMap 的区别

一句话总结

  • Map 是"规范/标准"(接口)

  • HashMap 是"具体实现"(实现类)

生活类比

▎ Map 就像"交通工具"这个概念

▎ HashMap 就像"汽车",是交通工具的一种具体实现

交通工具(Map 接口)

├── 汽车(HashMap) ← 最常用,速度快

├── 火车(TreeMap) ← 会自动排序

└── 自行车(LinkedHashMap) ← 保持插入顺序

接口 vs 实现类

Map 是接口,只定义了"能做什么",但不管"怎么做":

// Map 接口规定了这些方法必须有:

put(key, value) // 存数据

get(key) // 取数据

remove(key) // 删数据

containsKey(key) // 判断key是否存在

HashMap 是实现类,负责具体实现这些方法:

// HashMap 用"哈希表"这种数据结构来实现上面所有方法

为什么要这样写?

// 推荐写法:左边用接口,右边用实现类

Map<String, List<String>> map = new HashMap<>();

// 不推荐:左右都用实现类

HashMap<String, List<String>> map = new HashMap<>();

推荐左边写 Map 的好处:

将来想换一种实现,只改一处地方就够了:

// 想改成有序的?只改右边一个词

Map<String, List<String>> map = new TreeMap<>();

// 想改成保持插入顺序的?

Map<String, List<String>> map = new LinkedHashMap<>();

// 其他用到 map 的代码,一行都不用改!

如果左边写 HashMap,换实现时就要改很多地方。

相关推荐
java小白小20 小时前
Guava Cache 本地缓存
java
梦梦代码精20 小时前
LikeShop 二次开发扩展能力白皮书——面向业务增长的可扩展电商架构实践
java·架构·github
极客先躯20 小时前
高级java每日一道面试题-2025年12月05日-实战篇[Dockerj]-Docker 安装后的默认存储路径是什么?如何修改?
java·docker·默认存储路径在不同系统上的区别·linux overlay2·修改存储路径的理论方法·修改流程中的关键理论点
祁_z20 小时前
LangSmith 实操指南「Agent 可观测性系统」
java·服务器
小雅痞21 小时前
[Java][Leetcode hard] 76. 最小覆盖子串
java·算法·leetcode
admiraldeworm21 小时前
c -> true 导致异常返回 404 问题排查
c语言·开发语言
MegaDataFlowers21 小时前
代码自动生成
java
dllxhcjla21 小时前
Spring全套
java·后端·spring
qq_3759163721 小时前
kettle菜鸟教程
开发语言·kettle
qq_2546744121 小时前
Alpine Linux 基于 Debian 等系统的常规 Nginx
开发语言