前言
用好hash和sort,可为解题提供遍历。
一、字母异位词
二、多种解法刨析
package com.xhu.offer.top100;
import java.util.*;
//字母异位词分组
public class GroupAnagrams {
//暴力两两比较
//改:暴力和List中的第一个字符串比较,如果是就加入。全都不是就另起炉灶。
//总结:Time:O(n*ln*n),Space:O(n*ln)
public List<List<String>> groupAnagrams(String[] strs) {
int ln = strs.length;
List<List<String>> rs = new ArrayList<>();
for (int i = 0; i < ln; i++) {
int j = 0, size = rs.size();
for (; j < size; j++) {
//bug1:如果两个字符串长度都不相等就不用比了。
List<String> cur = rs.get(j);
if (cur.get(0).length() == strs[i].length() && isMatch(strs[i], m.get(j))) {
cur.add(strs[i]);
break;
}
}
if (j == size) {
List<String> el = new ArrayList<>();
el.add(strs[i]);
rs.add(el);
//设置第一个的字符hash
int[] hash = getHash(strs[i]);
m.put(num++, hash);
}
}
return rs;
}
/**
* 得到一个字符串的字符hash
*
* @param str
* @return
*/
private int[] getHash(String str) {
int[] rs = new int[26];
for (char c : str.toCharArray()) {
rs[c - 'a']++;
}
return rs;
}
Map<Integer, int[]> m = new HashMap<>();
int num = 0;
/**
* 用于比较两个字符串是否为字母异位词
*
* @param str
* @return
*/
private boolean isMatch(String str, int[] hash) {
int[] h = new int[26];
for (char c : str.toCharArray()) {
if (++h[c - 'a'] > hash[c - 'a']) return false;
}
return true;
}
public static void main(String[] args) {
String[] strs = new String[]{"eat", "tea", "tan", "ate", "nat", "bat"};
new GroupAnagrams().groupAnagrams(strs);
}
}
//一题多解,排序字符
//Time:O(N*K*logK):Space:O(n*k),k为最大字母长度。
class GroupAnagrams2 {
//排序字符,sort+hash 赋能
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> hash = new HashMap<>();
for (String str : strs) {
char[] arr = str.toCharArray();
Arrays.sort(arr);
String key = String.valueOf(arr);
List<String> el = hash.containsKey(key) ? hash.get(key) : new ArrayList<>();
el.add(str);
if (!hash.containsKey(key)) hash.put(key, el);
}
return new ArrayList<>(hash.values());
}
}
//一题多解,计数法
//Time:O(n*(k+26)),Space:O(n*(k+26)),k为最大字母长度。
class GroupAnagrams3 {
//计数字符,计数+hash 赋能
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> hash = new HashMap<>();
for (String str : strs) {
int[] arr = new int[26];
for (char c : str.toCharArray()) ++arr[c - 'a'];
StringBuilder sb = new StringBuilder();
int cnt = 0;
for (int i : arr) sb.append(i).append(arr[cnt++]);
String key = sb.toString();
List<String> el = hash.containsKey(key) ? hash.get(key) : new ArrayList<>();
el.add(str);
if (!hash.containsKey(key)) hash.put(key, el);
}
return new ArrayList<>(hash.values());
}
}
总结
1)用好hash和sort,可为解题提供遍历。
2)一题多解,打开视野。
参考文献
[1] LeetCode 字母异位词
[2] LeetCode 字母异位词官网题解