【算法】字母异位词分组

150 阅读3分钟

题目:字母异位词分组 

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 

 示例 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] 仅包含小写字母 

 题目分析:当我看到这道题的时候,这道题考查的就是找出所有的包含相同字母的单词(单词中的字母顺序是不固定的)。

我有以下几个疑惑点: 

第一、怎么进行比对 

举个例子,比如 输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]] 那怎么拿"eat"去和strs数组中的其他值进行比对,有没有统一的比对标准,我原先想的是先比较字符串的长度,然后再比较每个字母是否相同,这样复杂度就一下子上去了。 最后思考的得到的解决方案是:通过先把字符串转成数组,再进行排序,然后再转成字符串。如果是字符包含的字母相同,则最后得到转化之后的字符串都是一样的,接着再进行比较,这样复杂度降低了,逻辑更清晰了。

 第二、怎么保存相同的字母的字符串 

我原先的构想是先声明一个空数组a,来存储相同的字母的字符串,然后再声明一个大的数组A来存储这个a(会有很多个这样的a数组)。这样的话,复杂度一下就上去了。 这一步思考的得到的解决方案是使用map来进行存储,使用转化后得到的字符串当做map的key值,value刚开始是一个数组(这个数组的初始化值就是刚刚遍历到的那个值)。这样就解决了怎么保存相同的字母的字符串的问题。

那通过解决上面这两个疑问点,也相当于解答出了这道题; 具体代码如下:

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
    let strsMap = new Map()
    for (let str of strs) {
        // 字符串先转化成数组,然后对数组进行排序,排序之后,再转化为字符串。(相同字母组成的字符串最后转为的字符串都是一样的值)
        let switchStr = str.split('').sort().join('');// 这里注意split和join的用法,传入分割的字符        // 如果map中包含转化后的字符串,则把这个str push到数组中
        if (strsMap.has(switchStr)) {
            strsMap.get(switchStr).push(str);
        } else {
            // 如果map中不包含转化后的字符串,则用map.set设置key,value,key值为转化之后的值,value为初始化的数组
            strsMap.set(switchStr, [str])
        }
    }
    // 输出最后得到的数组值
    return Array.from(strsMap.values())
};