题目描述
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
难度:Middle
前置知识
- 哈希表
- 排序
公司
- 阿里
- 腾讯
- 百度
- 字节
思路
一个简单的解法就是遍历数组,然后对每一项都进行排序,然后将其添加到 hashTable 中,最后输出 hashTable 中保存的值即可。
这种做法空间复杂度 O(n), 假设排序算法用的快排,那么时间复杂度为 O(n * klogk), n 为数组长度,k 为字符串的平均长度
代码:
var groupAnagrams = function (strs) {
const hashTable = {};
function sort(str) {
return str.split("").sort().join("");
}
// 这个方法需要排序,因此不是很优,但是很直观,容易想到
for (let i = 0; i < strs.length; i++) {
const str = strs[i];
const key = sort(str);
if (!hashTable[key]) {
hashTable[key] = [str];
} else {
hashTable[key].push(str);
}
}
return Object.values(hashTable);
};
下面我们介绍另外一种方法,我们建立一个 26 长度的 counts 数组(如果区分大小写,我们可以建立 52 个,如果支持其他字符依次类推)。
然后我们给每一个字符一个固定的数组下标,然后我们只需要更新每个字符出现的次数。 最后形成的 counts 数组如果一致,则说明他们可以通过
交换顺序得到。这种算法空间复杂度 O(n), 时间复杂度 O(n * k), n 为数组长度,k 为字符串的平均长度.
实际上,这就是桶排序的基本思想。 很多题目都用到了这种思想, 读者可以留心一下。
关键点解析
- 桶排序
代码
- 语言支持: Javascript,Python3
/**
* @来源: Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
* @介绍:前端中文网是以前端进阶资源教程分享为主的专业网站,包括:前端、大厂面试题、typescript教程、程序人生、React.js
* @lc app=leetcode id=49 lang=javascript
*
* [49] Group Anagrams
*/
/**
* @param {string[]} strs
* @return {string[][]}
*/
var groupAnagrams = function (strs) {
// 类似桶排序
let counts = [];
const hashTable = {};
for (let i = 0; i < strs.length; i++) {
const str = strs[i];
counts = Array(26).fill(0);
for (let j = 0; j < str.length; j++) {
counts[str[j].charCodeAt(0) - "a".charCodeAt(0)]++;
}
const key = counts.join("");
if (!hashTable[key]) {
hashTable[key] = [str];
} else {
hashTable[key].push(str);
}
}
return Object.values(hashTable);
};
Python3 Code:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
"""
思路同上,在Python中,这里涉及到3个知识点:
1. 使用内置的 defaultdict 字典设置默认值;
2. 内置的 ord 函数,计算ASCII值(等于chr)或Unicode值(等于unichr);
3. 列表不可哈希,不能作为字典的键,因此这里转为元组;
"""
str_dict = collections.defaultdict(list)
for s in strs:
s_key = [0] * 26
for c in s:
s_key[ord(c)-ord('a')] += 1
str_dict[tuple(s_key)].append(s)
return list(str_dict.values())
复杂度分析
其中 N 为 strs 的长度, M 为 strs 中字符串的平均长度。
- 时间复杂度:$O(N * M)$
- 空间复杂度:$O(N * M)$
- 原题leetcode链接:https://leetcode-cn.com/problems/group-anagrams/
更多题解可以访问我的 码农周刊 仓库:https://github.com/meibin08/free-programming-books, 一起学习更多前端前沿知识。
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com