LeetCode 49: 字母异位词分组 Group Anagrams
LeetCode 49: 字母异位词分组 Group Anagrams
题目:
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
Given an array of strings, group anagrams together.
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
- 所有输入均为小写字母。
- 不考虑答案输出的顺序。
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
解题思路:
题目要求是 不管字母怎样排序只要字母相同都归为一类, 只要把所有单词的字母按一定规律排列好, 只要每个单词的字母按规律排好后组成的字符串相同, 则归为一类
排序字母解题:
用哈希映射 {Key : Value} Key 为排好序的字符串, Value 为数组, 存储与 Key 字母相同的单词, 遍历每个单词并排序字母, 查找排序好的字符串是否存在于 Keys, 利用哈希映射可将查找操作时间复杂度降为 O(1)
其解题逻辑为(这里按字母升序排列):
输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
建立哈希映射 map = {}
遍历该字符串数组:
第一个单词: "eat" --> "aet"
"aet" 不存在于 map, 建立映射 {"aet" : [ "eat" ] }
第二个单词: "tea" --> "aet"
"aet" 存在于 map, 加入其 Values {"aet" : [ "eat" , "tea" ] }
第三个单词: "tan" --> "ant"
"ant" 不存在于 map, 建立映射 {"aet" : [ "eat" , "tea" ] ; "ant" : [ "tan" ] }
第四个单词: "ate" --> "aet"
"aet" 存在于 map, 加入其 Values {"aet" : [ "eat" , "tea" , "ate" ] ; "ant" : [ "tan" ] }
......
map = {"aet" : [ "eat" , "tea" , "ate" ] ; "ant" : [ "tan" , "nat"] ; "abt" : [ "bat" ] }
返回该哈希映射的 Values 组成的数组:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
复杂度:
时间复杂度:O(N*(K*logK)),其中 N 是 strs 的长度,而 K 是 strs 中字符串的最大长度。遍历每个字符串时复杂度为 O(N)。使用内置排序函数排序字符串中的字母的时间复杂度为 O(K*logK)。
空间复杂度:O(N*K),存储在 map 中数据所占用的空间。
统计字频解题:
这种解题方法还可以再优化, 可以省略对字符串排序的操作。
仔细想想,一个单词最多由 26 个英文字母组成, 不就也可以建立一个哈希映射吗? 如:
对于单词 "aeat" :
建立哈希映射{ 'a' : 2 ; 'e' : 1; t : 1 }
key 为出现的单词, value 出现的频次。如果遍历每个 key 判断字母是否相等, 再判断出现次数是否相等, 这显然是更复杂了。
可以将每个字母出现的频次组成连续字符:
每个字母 a-z 出现频次: [2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0]
组成字符串: "20001000000000000001000000"
只需判断每个单词的字母频次字符串是否相同就可以了。
对于求词频还可以优化, 字母数量固定 26 个, 直接建立一个长度为 26 的数组, 其索引代表二十六个字母位, 遍历单词中的字母, 字母每出现一次, 数组中代表该字母的元素值加 1。
这样就避免了排序操作
排序字母解题:
Java:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
if(strs.length==0) return new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();//建立映射关系
for (String s : strs) {//遍历该字符串数组
char[] chs = s.toCharArray();//转成字符
Arrays.sort(chs);//排序字符串字母
String key = String.valueOf(chs);//转成字符串
if(!map.containsKey(key)) map.put(key, new ArrayList<>());//如果 key 不存在, 新建映射关系
map.get(key).add(s);//加入其对应的 Value 所在的数组
}
return new ArrayList(map.values());//返回 Values 组成的数组
}
}
Python:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
ans = collections.defaultdict(list) # 建立映射关系
for s in strs: # 遍历该字符串数组
ans[tuple(sorted(s))].append(s) # sorted(s):排序字符串字母, 并加入其对应的 Value 所在的数组
return ans.values() # 返回 Values 组成的数组
统计字频解题:
Java:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
if (strs.length == 0) return new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();// 建立映射关系
for (String s : strs) {//遍历该字符串数组
int[] count = new int[26];//建立一个 26 字母的映射关系
for (char c : s.toCharArray()) count[c - 'a']++;//遍历字字符串每个字母统计每个字母出现的频次
String key = Arrays.toString(count);//转成字符串
if (!map.containsKey(key)) map.put(key, new ArrayList<>());//如果 key 不存在, 新建映射关系
map.get(key).add(s);//加入其对应的 Value 所在的数组
}
return new ArrayList(map.values());//返回 Values 组成的数组
}
}
Python:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
ans = collections.defaultdict(list)# 建立映射关系
for s in strs: # 遍历该字符串数组
count = [0] * 26 # 建立一个 26 字母的映射关系
for c in s: # 遍历字字符串每个字母
count[ord(c) - 97] += 1 # 每个字母出现的频次(元素值)加1
ans[tuple(count)].append(s) # 加入其对应的 Value 所在的数组
return ans.values() # 返回 Values 组成的数组
欢迎关注微信.公.众号: 爱写Bug

LeetCode 49: 字母异位词分组 Group Anagrams的更多相关文章
- Java实现 LeetCode 49 字母异位词分组
49. 字母异位词分组 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", & ...
- Leetcode 49.字母异位词分组
字母异位词分组 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", " ...
- LeetCode 49. 字母异位词分组(Group Anagrams)
题目描述 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", "ta ...
- [Swift]LeetCode49. 字母异位词分组 | Group Anagrams
Given an array of strings, group anagrams together. Example: Input: ["eat", "tea" ...
- 【LeetCode】49. 字母异位词分组
49. 字母异位词分组 知识点:字符串:哈希表 题目描述 给你一个字符串数组,请你将 字母异位词 组合在一起.可以按任意顺序返回结果列表. 字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源 ...
- LeetCode:字母异位词分组【16】
LeetCode:字母异位词分组[16] 题目描述 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", &quo ...
- leetcode TOP100 字母异位词分组
字母异位词分组 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 思路: 一个map,将每个字符串字符进行记数,字符作为map的key,次数初始为零,以此来标识字 ...
- Leetcode题库——49.字母异位词分组【##】
@author: ZZQ @software: PyCharm @file: leetcode49_groupAnagrams.py @time: 2018/11/19 13:18 要求:给定一个字符 ...
- Leetcode题目49.字母异位词分组(中等)
题目描述: 给定一个字符串数组,将字母异位词组合在一起.字母异位词指字母相同,但排列不同的字符串. 示例: 输入: ["eat", "tea", "t ...
随机推荐
- Redis实战 | 5种Redis数据类型详解
我们知道Redis是目前非常主流的KV数据库,它因高性能的读写能力而著称,其实还有另外一个优势,就是Redis提供了更加丰富的数据类型,这使得Redis有着更加广泛的使用场景.那Redis提供给用户的 ...
- RocketMQ 整合 DLedger(多副本)即主从切换实现平滑升级的设计技巧
目录 1.阅读源码之前的思考 2.从 Broker 启动流程看 DLedger 2.1 构建 DefaultMessageStore 2.2 增加节点状态变更事件监听器 2.3 调用 DefaultM ...
- 封装读取文件(node js)
我们都会简单的读取文件,今天我们就来讲一下用函数封装读取文件. 1.首先我们要先建好文件 2.我们在index.js里面写入代码: var http=require('http'); var fs=r ...
- SpringBoot IoC启动流程、初始化过程及Bean生命周期各个阶段的作用
目录 SpringBoot IoC启动流程.初始化过程及Bean生命周期各个阶段的作用 简述 首先明确IoC容器是啥 准备-SpringApplication的实例化 启动-SpringApplica ...
- IJKPlayerView设置Header播放视频的方法
播放b站视频连接的实测图 https://github.com/Rukey7/IjkPlayerView 使用库的连接 在用这个库播放b站视频连接的时候总是播放不了 检查了一下是因为b站视频连接需要验 ...
- 用函数式编程,从0开发3D引擎和编辑器(三):初步需求分析
大家好,本文介绍了Wonder的高层需求和本系列对应的具体功能点. 确定Wonder高层需求 业务目标 Wonder是web端3D开发的解决方案,包括引擎.编辑器,致力于打造开放.分享.互助的生态. ...
- 微信小程序 存储数据到本地以及本地获取数据
1.wx存储数据到本地以及本地获取数据 存到本地就是存到你的手机 wx.setStorageSync与wx.setStorage 1.1 wx.setStorageSync(string key, a ...
- ubuntu下安装tomcat,shutdown时报错:./catalina.sh:1:eval:/home/xxx/jdk/jre/bin/java:not found
该问题可能导致tomcat启动成功了,但是浏览器输入http://127.0.0.1:8080无法显示tomcat的欢迎界面 打开Tomcat安装目录下的bin文件下的setclasspath.sh, ...
- DiskCatalogMaker for Mac常见问题解答
DiskCatalogMaker for Mac是Mac上简单实用的磁盘管理工具,可以帮助您对多张光盘使用批量扫描模式, 生成缩略图图像选项,更加清晰,并请将其快速编目引擎与其他编目人员比较,在本篇文 ...
- Yii2中indexBy()的使用
在项目开发中经常会使用到一些特殊的值作为数组的索引,一般可以先查询出数据后数组循环拼接成所需的格式.不过YII2框架提供了一种更简单的方法indexBy(). 参考Yii文档:https://www. ...