[JS] 字母异位词分组与JS中对象键值特性

题目地址:LeetCode 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] 仅包含小写字母

这道题是一道经典的哈希表应用题,哈希表在这道题里面有两个应用:

  1. 对于一个单词,建立字母到字母出现次数的映射;
  2. 对于题目给定的单词数组,需要建立一个 特殊值 到单词组的映射;

其中的 特殊值 应该满足由单词计算得到,且不同的字母异位词的 特殊值 是相同的。

官方题解

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
    const map = new Object();
    for (let s of strs) {
        const count = new Array(26).fill(0);
        for (let c of s) {
            count[c.charCodeAt() - 'a'.charCodeAt()]++;
        }
        map[count] ? map[count].push(s) : map[count] = [s];
    }
    return Object.values(map);
};

第一层循环遍历的是词组里的单词。

for(let s of strs){
    const count = new Array(26).fill(0);
    ...
}

一开始我很疑惑,因为对于每一个单词,都新建了一个独立的count来计算这个单词中各个字母出现的次数。

这里的count就是上文说到的特殊值,用来判断字母异位词。

在一个单词遍历完所有字母后,count计算完毕,通过

map[count] ? map[count].push(s) : map[count] = [s];

特殊值 相同的单词分为一组。

我的困惑是每次的count都是新建的数组,每个单词的 特殊值 不同,每个单词都会单独成组。
但事实是

JS 对象特性

根据 JS 的语言特性,对象的key只能是字符串或者Symbol类型。

count作为数组类型,在被当作对象的key使用时,会进行隐式数据类型转换,被转换为一个字符串。

于是,只要有一些单词的字母计数一样,那么它们的count “序列化” 成字符串之后就是相等的。因此,可以被正确地分为一组。


测试

在 Node.js 中测试,使用一个数组作为对象的key来创建一个键值对,输出对象的keys发现自动被转换成字符串了。

热门相关:调教初唐   隐婚99天:首席,请矜持   梁医生又在偷偷套路我   婚婚欲睡:腹黑老公请节制   一世倾心:误惹腹黑师弟