[LeetCode] 49. Group Anagrams

Given an array of strings strs, group the anagrams together. You can return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Example 1:

Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]

Example 2:

Input: strs = [""]
Output: [[""]]

Example 3:

Input: strs = ["a"]
Output: [["a"]] 

Constraints:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] consists of lower-case English letters.

字母异位词分组。

给定一个字符串数组,将字母异位词组合在一起。可以按任意顺序返回结果列表。字母异位词指字母相同,但排列不同的字符串。

做这个题之前,需要做如下几个题,对anagram的概念有所了解。

242. Valid Anagram

383. Ransom Note

387. First Unique Character in a String

此题比较粗暴的解法是把 input 里面所有的单词都按照字母排序,形成一个新的单词。比如"eat"排序后会成为"aet",然后以"aet"为key,"eat"为 value 加入 hashmap。遍历完 input 之后,输出 hashmap 所有的 value 即可。

时间O(nlogn) - sort

空间O(n) - hashmap

JavaScript实现

 1 /**
 2  * @param {string[]} strs
 3  * @return {string[][]}
 4  */
 5 var groupAnagrams = function (strs) {
 6     const map = {};
 7     for (let str of strs) {
 8         const key = [...str].sort().join('');
 9         if (!map[key]) {
10             map[key] = [];
11         }
12         map[key].push(str);
13     }
14     return Object.values(map);
15 };

Java实现

 1 class Solution {
 2     public List<List<String>> groupAnagrams(String[] strs) {
 3         // corner case
 4         if (strs == null || strs.length == 0) {
 5             return new ArrayList<List<String>>();
 6         }
 7 
 8         // normal case
 9         HashMap<String, List<String>> map = new HashMap<>();
10         for (String str : strs) {
11             char[] ca = str.toCharArray();
12             Arrays.sort(ca);
13             String keyStr = String.valueOf(ca);
14             if (!map.containsKey(keyStr)) {
15                 map.put(keyStr, new ArrayList<String>());
16             }
17             map.get(keyStr).add(str);
18         }
19         return new ArrayList<List<String>>(map.values());
20     }
21 }

但是如上不是最优解,最优解还是要通过counting sort的思路来做。对于每个单词,需要创建一个长度为26的数组(题目说了只有小写)来存这个单词里面每个字母都分别出现过几次。这样每个单词最后形成的数组会长类似这样,

[ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ]
[ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ]
[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ]

然后把这个数组稍微变化一下,做成一个类似这样的string

1#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#0#0#0

把这个string当做hashmap的key。这样每个扫描过的单词都会变成这样,是错位词的单词们的string会长得一样,所以在hashmap中会被存到同一个key里面。最后以数组形式输出hashmap里面所有的value即可。或者中间不加#也能做,只需要把charArray convert成string即可,把这个string当做key存入hashmap。

时间O(n) - 没有排序

空间O(n)

JavaScript实现

 1 /**
 2  * @param {string[]} strs
 3  * @return {string[][]}
 4  */
 5 var groupAnagrams = function (strs) {
 6     const map = new Map();
 7     for (const s of strs) {
 8         const letters = Array(26).fill(0);
 9         for (const c of s) {
10             letters[c.charCodeAt(0) - 97]++;
11         }
12         console.log(letters);
13         const key = letters.join("#");
14         console.log(key);
15         let val = [];
16         if (map.has(key)) {
17             val = map.get(key);
18         }
19         val.push(s);
20         map.set(key, val);
21     }
22 
23     return Array.from(map.values());
24 };

Java实现

 1 class Solution {
 2     public List<List<String>> groupAnagrams(String[] strs) {
 3         // corner case
 4         if (strs == null || strs.length == 0) {
 5             return new ArrayList<>();
 6         }
 7 
 8         // normal case
 9         HashMap<String, List<String>> map = new HashMap<>();
10         for (String str : strs) {
11             char[] ca = new char[26];
12             for (char c : str.toCharArray()) {
13                 ca[c - 'a']++;
14             }
15             String key = String.valueOf(ca);
16             if (!map.containsKey(key)) {
17                 map.put(key, new ArrayList<>());
18             }
19             map.get(key).add(str);
20         }
21         return new ArrayList<>(map.values());
22     }
23 }

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/12231788.html