当前位置: 首页 > news >正文

LeetCode经典题解:49、字母异位词分组

LeetCode经典题解:字母异位词分组

“字母异位词分组”是哈希表应用的经典题目,解法思路清晰但细节易混。本文用“场景化记忆法”帮你吃透解法,从代码逻辑到记忆技巧一网打尽。

一、题目描述

题目:给你一个字符串数组,请你将字母异位词组合在一起。可以按任意顺序返回结果列表。
字母异位词是由重新排列源单词的所有字母得到的新单词(例如,“eat”和“tea”是字母异位词)。

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

二、最优解法:哈希表 + 特征归一

方法一:排序法(直观高效)

代码实现
import java.util.*;class Solution {public List<List<String>> groupAnagrams(String[] strs) {// 哈希表:key是"特征值"(排序后的字符串),value是同组异位词列表Map<String, List<String>> map = new HashMap<>();for (String s : strs) {// 将字符串转换为字符数组,排序后作为"特征值"char[] chars = s.toCharArray();Arrays.sort(chars);String key = new String(chars);// 若key不存在则创建新列表,否则直接添加到对应列表map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);}// 哈希表的值就是分组结果return new ArrayList<>(map.values());}
}
解法解析
  1. 核心逻辑:字母异位词排序后得到的字符串完全相同(例如“eat”和“tea”排序后都是“aet”),用排序后的字符串作为“特征值”,通过哈希表分组。
  2. 时间复杂度O(n * k log k)n 是字符串数量,k 是最长字符串长度,排序耗时 k log k)。
  3. 空间复杂度O(n * k)(哈希表存储所有字符串)。

方法二:字符频率法(适合长字符串)

代码实现
import java.util.*;class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String, List<String>> map = new HashMap<>();for (String s : strs) {// 统计26个小写字母的出现次数int[] count = new int[26];for (char c : s.toCharArray()) {count[c - 'a']++;}// 将频率数组转为字符串作为key(例如"1,0,2,...")StringBuilder key = new StringBuilder();for (int num : count) {key.append(num).append(','); // 加逗号避免歧义(如11和1,1)}map.computeIfAbsent(key.toString(), k -> new ArrayList<>()).add(s);}return new ArrayList<>(map.values());}
}
解法解析
  1. 核心逻辑:字母异位词的字符频率完全相同(例如“eat”和“tea”的 e:1, a:1, t:1),用频率数组的字符串形式作为“特征值”分组。
  2. 优势:避免排序耗时,适合字符串长(k 大)但字符集小(如仅小写字母)的场景。

三、为什么这样解?—— 异位词的“共性”与分组逻辑

1. 异位词的本质

字母异位词的核心共性是“字符种类和数量完全相同,顺序不同”。因此,只要找到一种“归一化”方法(如排序、统计频率),就能将异位词映射到同一“特征值”。

2. 哈希表的作用

哈希表的“键值对”结构天然适合“分组”:

  • 键(key):异位词的“特征值”(排序后的字符串或频率字符串),确保同一组异位词映射到同一键。
  • 值(value):存储同一组的所有异位词,最终直接返回所有值的集合。

四、高效记忆技巧:把逻辑变成“整理文件”的场景

用生活化场景理解代码,记住“角色+动作”即可还原解法:

1. 角色赋值

  • 哈希表(map):扮演“文件柜”,每个抽屉(key)对应一组异位词。
  • 排序/频率统计:扮演“标签机”,给每个字符串打“特征标签”(确保异位词标签相同)。
  • 字符串数组(strs):扮演“一堆待整理的文件”,需要按标签分类放进文件柜。

2. 场景故事:整理文件的流程

(以排序法为例)
你是档案管理员,要把一堆文件(strs)按“内容相同、顺序不同”分类:
① 拿起一份文件(字符串),用“标签机”(排序)给它打标签(排序后的字符串,如“tea”→“aet”);
② 查看文件柜(map)里有没有这个标签的抽屉:

  • 有则直接把文件放进去;
  • 没有则新建抽屉(key),再放文件;
    ③ 所有文件处理完后,文件柜里的抽屉就是分组结果。

3. 两种方法的记忆点

方法标签机(特征值)适用场景一句话总结
排序法排序后的字符串字符串短、字符集大“排序归一,哈希分组”
频率统计法字符频率拼接的字符串字符串长、字符集小(如26字母)“统计频率做标签,哈希来归类”

4. 对比记忆:和“两数之和”的关联

两道题都用哈希表实现“分组/配对”,核心逻辑相通:

  • 两数之和:用哈希表找“补数”(配对);
  • 异位词分组:用哈希表按“特征值”归类(分组)。
    共同点:哈希表是“中介”,通过键值映射解决“关联/分组”问题

五、实战拓展:变种题巩固思路

  1. 判断两个字符串是否为异位词:直接比较排序后的结果或频率数组。
  2. 异位词中的最长单词:分组后找每组中最长的字符串。
  3. 区分大小写/包含数字的异位词:扩展频率数组(如考虑26大写+26小写+10数字,共62长度)。

通过“文件分类”的场景记忆,字母异位词分组的解法会变得很直观。记住:算法的核心是“找共性→用工具(哈希表)实现映射”,而非死记代码。多思考“如何定义特征值”,就能应对各种变种场景。

http://www.dtcms.com/a/272375.html

相关文章:

  • 游戏开发问题记录
  • 数字孪生技术为UI前端赋能:实现产品设计的快速原型验证
  • 小程序开发平台,自主开发小程序源码系统,多端适配,带完整的部署教程
  • Day57
  • 从零开始搭建深度学习大厦系列-2.卷积神经网络基础(5-9)
  • Redis性能基准测试
  • 影刀 RPA:实时追踪网页变化,第一时间推送通知
  • 知微传感Lkam系列线扫轮廓仪SDK例程篇:设置工作逻辑
  • Ubuntu 20.04 下**安装 FFmpeg 5.1
  • TCP 保活(KeepAlive)机制详解
  • 汽车功能安全-软件集成和验证(Software Integration Verification)【验证方法用例导出方法输出物】10
  • Java入门之JDK下载和安装
  • Thrust库介绍与使用
  • 《汇编语言:基于X86处理器》第7章 整数运算(1)
  • 机器人接入AI的发展前景:从开发者视角看技术融合与生态构建
  • JavaScript中的Screen对象:你的屏幕“身份证”
  • 城市规则管理列表实现逻辑
  • 【Note】Linux Kernel 实时技术深入:详解 PREEMPT_RT 与 Xenomai
  • 【React】MQTT + useEventBus 实现MQTT长连接以及消息分发
  • 昇腾 k8s vnpu配置
  • 在Linux中,如何使用grep awk sed find?
  • 链式二叉树数据结构(递归)
  • 自动化——bat——批量复制所选的文件
  • 微服务架构的演进:迈向云原生——Java技术栈的实践之路
  • SpringBoot整合腾讯云新一代行为验证码
  • RabbitMQ 幂等性
  • Allegro PCB 手动添加元器件全流程解析
  • expect 安装入门手册
  • 【保姆级教程】基于anji-plus-captcha实现行为验证码(滑动拼图+点选文字),前后端完整代码奉上!
  • 人工智能-基础篇-28-模型上下文协议--MCP请求示例(JSON格式,客户端代码,服务端代码等示例)