Given an array of strings, group anagrams together. 同字母异位词anagrams 指字母相同,但排列不同的字符串。
Example:
Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
[“ate”,”eat”,”tea”],
[“nat”,”tan”],
[“bat”]
]
Note:
- All inputs will be in lowercase.
- The order of your output does not matter.
求解
方法一:排序数组分类
顺序不同, 所以可以考虑将所有词的字母按顺序排列, 从而快速分组
import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;class Solution {public List<List<String>> groupAnagrams(String[] strs) {HashMap<String, List<String>> map = new HashMap<String, List<String>>();if (strs.length == 0) return new ArrayList();for (String s : strs) {char[] cur = s.toCharArray();Arrays.sort(cur); // 复杂度: KlogKString key = String.valueOf(cur);if (!map.containsKey(key)){map.put(key, new ArrayList<>());}map.get(key).add(s);}return new ArrayList<List<String>>(map.values());}}
复杂度分析
时间复杂度:O(N KlogK),其中 N是 strs 的长度,而 K 是 strs 中字符串的最大长度。当我们遍历每个字符串时,外部循环具有的复杂度为 O(N)。然后,我们在 O(KlogK) 的时间内对每个字符串排序。
空间复杂度:O(NK),排序存储在 ans 中的全部信息内容。
方法二:按计数分类
当且仅当它们的字符计数(每个字符的出现次数)相同时,两个字符串是字母异位词。
我们可以将每个字符串 s 转换为字符数 count,由26个非负整数组成,表示a,b,c 的数量等。我们使用这些计数作为哈希映射的基础。
在 Java 中,我们的字符数 count 的散列化表示将是一个用 # 字符分隔的字符串。 例如,abbccc 将表示为 #1#2#3#0#0#0 ...#0 ,其中总共有26个条目。
class Solution {public List<List<String>> groupAnagrams(String[] strs) {if (strs.length == 0) return new ArrayList();Map<String, List> ans = new HashMap<String, List>();int[] count = new int[26];for (String s : strs) {Arrays.fill(count, 0);for (char c : s.toCharArray()) count[c - 'a']++;StringBuilder sb = new StringBuilder();for (int i = 0; i < 26; i++) {sb.append('#');sb.append(count[i]);}String key = sb.toString();if (!ans.containsKey(key)) ans.put(key, new ArrayList());ans.get(key).add(s);}return new ArrayList(ans.values());}}
复杂度分析
时间复杂度:O(NK),其中 N 是 strs 的长度,而 K 是 strs 中字符串的最大长度。计算每个字符串的字符串大小是线性的,我们统计每个字符串。
空间复杂度:O(NK),排序存储在 ans 中的全部信息内容。
