LeetCode字母异位词分组

题目描述

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

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

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

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

示例 2:

输入: strs = [""]

输出: [[""]]

示例 3:

输入: strs = ["a"]

输出: [["a"]]

解题思路

对于输入数组中的每个字符串,通过排序字符来创建一个唯一的键,然后根据这个键将变位词分组。最后,将所有分组的结果收集到一个数组中并返回。这种方法不依赖于外部库,只使用了JavaScript的内置Map对象。

代码

javascript 复制代码
/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
    var res = [];
    var map = new Map();
    for(var i=0;i<strs.length;i++){
        var k = strs[i].split('').sort().join('');
        if(map.has(k)){
            map.get(k).push(strs[i]);
        }else{
            map.set(k, [strs[i]]);    
        }
    }
    map.forEach((val, key)=>{
        res.push(val);
    })
    return res;
    
};

代码分析

这段代码用于将一个字符串数组strs中的变位词分组。下面是逐行分析:

  1. var groupAnagrams = function(strs) {

    • 定义了一个名为groupAnagrams的函数,它接受一个参数strs,这是一个字符串数组。
  2. var res = [];

    • 定义了一个空数组res,用于存储最终的分组结果。
  3. var map = new Map();

    • 创建了一个新的Map对象,用于存储中间的分组结果。Map对象是一种键值对集合,可以记住键的原始插入顺序。
  4. for(var i=0;i<strs.length;i++){

    • 开始一个循环,遍历输入数组strs中的每个字符串。
  5. var k = strs[i].split('').sort().join('');

    • 对于当前循环中的字符串strs[i],将其拆分成字符数组,对数组进行排序,然后将排序后的数组重新连接成一个字符串。这个字符串k将作为分组的键。
  6. if(map.has(k)){

    • 检查Map对象中是否已经存在键k
  7. map.get(k).push(strs[i]);

    • 如果键k已经存在,那么将当前字符串strs[i]添加到与键k相关联的数组中。
  8. }else{

    • 如果键k不存在,执行下面的代码。
  9. map.set(k, [strs[i]]);

    • 将键k和一个新的数组(包含当前字符串strs[i])作为键值对添加到Map对象中。
  10. }

    • 结束if语句。
  11. }

    • 结束for循环。
  12. map.forEach((val, key)=>{

    • 使用Map对象的forEach方法遍历所有键值对。
  13. res.push(val);

    • 对于每个键值对,将值(即分组后的字符串数组)添加到结果数组res中。
  14. })

    • 结束forEach方法的回调函数。
  15. return res;

    • 函数返回结果数组res,它包含了所有分组后的变位词数组。
  16. };

    • 结束函数定义。

案例:

使用字符串数组strs = ["eat", "tea", "tan", "ate", "nat", "bat"]来演示groupAnagrams函数如何工作。下面是具体的步骤和结果:

  1. 初始化

    • res 初始化为空数组。
    • map 初始化为一个新的空Map对象。
  2. 遍历字符串数组

    • 对于每个字符串,我们通过strs[i].split('').sort().join('')生成一个排序后的字符串作为键。
  3. 分组

    • 根据生成的键,我们将字符串分组到map中。
  4. 收集结果

    • 遍历map,将每个分组的字符串数组添加到结果数组res中。
  5. 返回结果

手动模拟这个过程:

  • 对于字符串 "eat",排序后的键是 "aet"
    • map 现在包含 {"aet": ["eat"]}
  • 对于字符串 "tea",排序后的键也是 "aet"
    • map 更新为 {"aet": ["eat", "tea"]}
  • 对于字符串 "tan",排序后的键是 "ant"
    • map 现在包含 {"aet": ["eat", "tea"], "ant": ["tan"]}
  • 对于字符串 "ate",排序后的键同样是 "aet"
    • map 更新为 {"aet": ["eat", "tea", "ate"], "ant": ["tan"]}
  • 对于字符串 "nat",排序后的键是 "ant"
    • map 更新为 {"aet": ["eat", "tea", "ate"], "ant": ["tan", "nat"]}
  • 对于字符串 "bat",排序后的键是 "abt"
    • map 现在包含 {"aet": ["eat", "tea", "ate"], "ant": ["tan", "nat"], "abt": ["bat"]}
  1. 最终结果
    • 遍历map,将值(即分组的数组)添加到res中,得到最终结果。

最终的res数组将是:

javascript 复制代码
[
  ["eat", "tea", "ate"],
  ["tan", "nat"],
  ["bat"]
]

这个结果表示 "eat"、"tea""ate" 是一组变位词,"tan" 和 "nat" 是另一组变位词,而 "bat" 没有变位词,因此它自己为一组。

知识点

sort 方法可以用于排序数组中的元素。在 JavaScript 中,当你对一个字符串调用 split('') 方法时,它会将字符串分割成一个字符数组。例如,字符串 "eat" 会被分割成 ["e", "a", "t"]

然后,当你对这个字符数组调用 sort() 方法时,它会根据字符的默认排序顺序(通常是按照 Unicode 码点)对数组中的元素进行排序。对于字母,这意味着它们会按照字母表的顺序进行排序。

例如:

javascript 复制代码
"eat".split('').sort().join(''); // "aet"

在这个例子中,字符串 "eat" 被分割成 ["e", "a", "t"],然后排序成 ["a", "e", "t"],最后通过 join('') 方法重新组合成一个字符串 "aet"

解释 map.get(k).push(strs[i])

  1. map.get(k):

    • map 是一个 Map 对象,它存储键值对。
    • k 是一个键,通常是通过某种方式(如前面提到的排序字符串)计算得到的。
    • map.get(k) 方法用于获取与键 k 相关联的值。如果键 k 存在于 Map 中,它将返回与该键关联的值;如果键不存在,它将返回 undefined
  2. .push(strs[i]):

    • push 是一个数组方法,用于将一个或多个元素添加到数组的末尾,并返回新的数组长度。
    • strs[i] 是当前遍历到的字符串,其中 strs 是原始的字符串数组,i 是当前的索引。

功能描述

  • 当执行 map.get(k).push(strs[i]) 时,首先通过 map.get(k) 获取与键 k 相关联的数组。
  • 如果该键 k 已经存在于 map 中,那么 map.get(k) 将返回一个数组,然后 .push(strs[i]) 将当前字符串 strs[i] 添加到这个数组的末尾。
  • 如果键 k 不存在,map.get(k) 返回 undefined,而 undefined 没有 push 方法,这将导致运行时错误。因此,通常在这之前会检查该键是否存在,或者使用 map.has(k) 来确保键存在。
相关推荐
青い月の魔女10 分钟前
数据结构初阶---二叉树
c语言·数据结构·笔记·学习·算法
林的快手1 小时前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
千天夜1 小时前
多源多点路径规划:基于启发式动态生成树算法的实现
算法·机器学习·动态规划
从以前1 小时前
准备考试:解决大学入学考试问题
数据结构·python·算法
.Vcoistnt2 小时前
Codeforces Round 994 (Div. 2)(A-D)
数据结构·c++·算法·贪心算法·动态规划
柒月的猫2 小时前
方格分割(蓝桥杯2017年试题D)
职场和发展·蓝桥杯
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战训练三)
数据结构·c++·算法·图论
柒月的猫4 小时前
翻转(蓝桥杯2023大学C组试题E)
职场和发展·蓝桥杯
Dream it possible!4 小时前
LeetCode 热题 100_LRU 缓存(35_146_中等_C++)(哈希表 + 双向链表)(构造函数声明+初始化列表=进行变量初始化和赋值)
c++·leetcode·缓存
我码玄黄4 小时前
正则表达式优化之算法和效率优化
前端·javascript·算法·正则表达式