题目:
49. 字母异位词分组
中等
相关标签
相关企业
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i]
仅包含小写字母
前置知识点:
Map():
Map()
是 JavaScript 中的一个构造函数,用于创建 Map
对象。Map
对象保存键值对的集合,并且能够记住键的原始插入顺序。任何值(对象或者原始值)都可以作为一个键或一个值。
以下是一些关于 Map
对象的关键点:
-
键值对存储:
Map
存储键值对,其中键和值可以是任意类型。 -
迭代顺序:
Map
对象记住了元素的添加顺序,因此迭代操作会按照元素的插入顺序进行。 -
大小可查询:
Map
对象有一个size
属性,可以返回映射中元素的个数。 -
可以有相同的键:与对象不同,
Map
允许键值相等(例如,两个字符串键 "key" 和 "key" 被认为是相同的键)。 -
内置方法:
.set(key, value)
:设置映射中键的值,并返回 Map 对象。.get(key)
:返回指定键的值。.has(key)
:如果映射中包含键,返回 true,否则返回 false。.delete(key)
:如果映射中包含键,删除它并返回 true,否则返回 false。.clear()
:移除映射中的所有键值对。
-
迭代器:
Map
对象提供了迭代器方法,如.keys()
、.values()
和.entries()
,允许你遍历键、值或键值对。 -
WeakMap:与
Map
类似,但WeakMap
只接受对象作为键,并且这些键是弱引用,不阻止垃圾回收。 -
兼容性:
Map
是 ES6(ECMAScript 2015)引入的,因此在一些旧的浏览器中可能不被支持,或者需要 polyfill。
下面是一个简单的 Map
使用示例:
Map
对象是现代JavaScript开发中处理键值对数据的一个非常有用的工具,特别是在需要保持元素顺序或使用非字符串键的场景中
for (const str of strs)
这段代码是 JavaScript 中的一个迭代语句,用于遍历一个可迭代对象(比如数组、字符串或 Map
对象)中的每个元素。具体来说,for...of
循环是 ES6(ECMAScript 2015)引入的新特性,它提供了一种简洁的方式来遍历可迭代对象。
下面是对这段代码的逐部分解释:
-
for
:这是 JavaScript 中的循环关键字,用于开始一个循环结构。 -
(const str of strs)
:这是一个for...of
循环的声明部分。这里声明了一个循环变量str
,并且在每次迭代中,str
都会被设置为可迭代对象strs
的当前元素。const
关键字意味着str
在循环体内是只读的,你不能重新赋值给str
。 -
strs
:这是可迭代对象的名称,它应该是一个数组、字符串、Map
对象或其他实现了迭代器接口的对象。 -
{}
:这是循环体的开始和结束标记。在大括号之间的代码是循环体,每次迭代都会执行。
整个 for...of
循环的意思是:对于 strs
中的每个元素,将其赋值给变量 str
,然后执行一次循环体内的代码块。
这里有一个使用 for...of
循环遍历数组的例子:
在这个例子中,fruits
是一个包含三种水果名称的数组。for...of
循环遍历这个数组,每次迭代将数组中的当前元素赋值给变量 fruit
,然后打印出来。
这种循环结构使得遍历可迭代对象变得非常简洁和易于阅读。
Array(26).fill(0)
Array(26).fill(0)
是 JavaScript 中的一个表达式,用于创建一个长度为 26 的数组,并将所有元素初始化为 0。下面是对这个表达式的详细解释:
-
Array(26):这是
Array
构造函数的调用,它创建一个新的数组,其长度为 26。注意,这个数组的索引从 0 到 25,共有 26 个元素。 -
.fill(0):这是
Array
的fill
方法。这个方法会改变所有元素的值到你提供的参数值。在这个例子中,方法的参数是0
,所以数组中的每个元素都会被设置为 0。
整个表达式的结果是一个新的数组,其内容如下:
这个数组可以用于初始化一个计数器数组,例如在实现某些算法时,可能需要一个数组来跟踪不同元素的出现次数。使用 fill
方法可以快速地初始化这样一个数组,而不需要手动设置每个元素的值。
.charCodeAt(i)
在 JavaScript 中,.charCodeAt(i)
是 String
对象的一个方法,它返回字符串中指定索引 i
处字符的 Unicode 编码。这里的 i
是一个从 0 开始的整数索引,表示你想要获取编码的字符在字符串中的位置。
语法:
str.charCodeAt(index)
str
是任意一个字符串。index
是一个介于 0 和str.length - 1
之间的整数,表示你想要获取的字符在字符串中的位置。
返回值:
- 返回位于指定索引的字符的 Unicode 编码值。如果索引超出了字符串的边界,
charCodeAt
将返回NaN
。
示例:
在这个示例中,str
是字符串 "Hello, World!"
,调用 charCodeAt(0)
会获取到第一个字符 'H'
的 Unicode 编码,其值为 72。
注意事项:
charCodeAt
是大小写敏感的,所以'A'
和'a'
会返回不同的编码值。- Unicode 编码是一个数字,表示字符在 Unicode 标准中的位置。
用途:
charCodeAt
方法常用于需要操作字符编码的场景,比如检测字符串中的特定字符,或者在某些编码转换算法中。
兼容性:
charCodeAt
是 ECMAScript 标准的一部分,因此在所有现代浏览器和 JavaScript 环境中都可用。
...map.get(key)
...:扩展运算符用于将数组或 Map
对象中的元素展开到一个新的数组中。例如,如果你有一个 Map
对象,你可以使用扩展运算符将其转换为数组:
详细解析
这段代码是一个 JavaScript 函数,用于解决一个称为“分组同位素”(Group Anagrams)的算法问题。同位素(Anagrams)是指字母重新排列后形成的不同单词,例如 "abc" 可以重新排列为 "bca" 或 "cab",这些单词就是一组同位素。
让我们逐步解析这个函数:
-
函数定义:
这里定义了一个名为
groupAnagrams
的函数,它接受一个字符串数组strs
作为参数。 -
空数组检查:
如果输入数组是空的,函数直接返回一个空数组。
-
创建 Map 对象:
创建一个新的
Map
对象来存储同位素的分组。 -
遍历字符串数组:
使用
for...of
循环遍历输入的字符串数组strs
。 -
创建字符计数数组:
对于每个字符串,创建一个长度为 26 的数组
characters
,用来计数每个字母(a-z)出现的次数,初始值都设为 0。 -
计数每个字符的出现次数:
内部循环遍历字符串的每个字符,使用
charCodeAt
方法获取字符的 ASCII 值,然后减去 97('a' 的 ASCII 值),得到 0-25 的索引,对应字母表中的 a-z。然后,更新characters
数组中相应索引的计数。 -
生成排序后字符的字符串作为 Map 的键:
将
characters
数组中的计数连接成一个字符串,用作Map
的键。由于同位素具有相同的字符计数,这个字符串可以作为区分不同同位素组的依据。 -
分组同位素:
如果
Map
中已经存在当前字符串的键,则将字符串添加到对应的数组中;如果不存在,则创建一个新的数组,并将字符串作为第一个元素。 -
构建结果数组:
创建结果数组
result
,遍历Map
的每个键值对,并将每个键值对的值(即同位素组)添加到结果数组中。 -
返回结果:
返回包含同位素组的数组。
这个算法的核心思想是利用每个字符串的字符计数作为分组的依据。由于同位素具有相同的字符计数,这种方法可以有效地将它们分组在一起。注意,这里使用的 join(" ")
是为了解决一个特定的问题,即当字符出现次数完全相同时,直接 join
可能会造成不同的字符串具有相同的键值,通过加入空格或其他字符作为分隔符可以保证键的唯一性。
总结
这道算法题要求将一个字符串数组中的同位素(即字母可以重新排列形成的单词)分组。以下是解决这个问题的步骤总结:
-
空数组检查: 如果输入的字符串数组
strs
是空的,直接返回空数组。 -
创建 Map 对象: 使用 JavaScript 的
Map
对象来存储同位素的分组。Map
的键将是每个字符串的字符计数的字符串表示,值将是具有相同字符计数的字符串数组。 -
遍历字符串数组: 使用
for...of
循环遍历输入数组中的每个字符串。 -
创建字符计数数组: 对于每个字符串,创建一个长度为 26 的数组
characters
,用于计数每个字母(a-z)出现的次数,初始值都设为 0。 -
计数每个字符的出现次数: 内部循环遍历当前字符串的每个字符,使用
charCodeAt
方法获取字符的 ASCII 值,并减去 97('a' 的 ASCII 值),得到 0-25 的索引,然后更新characters
数组中相应索引的计数。 -
生成排序后字符的字符串作为 Map 的键: 将
characters
数组中的计数连接成一个字符串,用作Map
的键。这个字符串表示了字符串中每个字母的出现次数。 -
分组同位素: 使用
Map
对象来分组同位素。如果Map
中已经存在由字符计数字符串表示的键,则将当前字符串添加到对应的值数组中;如果不存在,则创建一个新的键值对,并将当前字符串作为值数组的第一个元素。 -
构建结果数组: 在所有字符串都被处理后,创建一个结果数组
result
。遍历Map
对象,将每个键对应的值(即同位素组)添加到result
数组中。 -
返回结果: 返回
result
数组,它包含了分组后的同位素数组。 -
确保键的唯一性: 为了避免具有相同字符计数但不同字符顺序的字符串被错误地分到同一组,可以使用空格或其他字符作为分隔符来连接
characters
数组,以确保每个键都是唯一的。
通过这种方法,我们可以有效地将具有相同字符但可能不同顺序的字符串分组到一起,解决了“分组同位素”的算法问题。
复制再试一次分享