原题:字母异位词分组
思路:字符串中字符的种类和出现次数相同,基于这个规律做哈希
思路
每个字符串中字符的种类和出现次数必定相同,要基于此求出哈希值 hashCode
判断哈希表上是否有值 hashMap.has(hashCode)
,没有就新建数组放在哈希表上,同时推入到结果数组中,有则直接往其中推入当前字符串 hashMap.get(hashCode).push(str)
1. 初始化
1 2 3 4 5 6
| const result = [];
const hashMap = new Map();
const aCode = 'a'.charCodeAt(0);
|
1. 求字符串对应哈希值
循环字符串列表,对每个字符串求哈希值
题目中提示只会有小写字母,所以我们申请一个长度 26 的数组,用于计算每个字母的出现次数,并且把其值初始化为 0
1 2 3 4
| const counter = new Array(26); for (let j = 0; j < counter.length; j++) { counter[j] = 0; }
|
遍历当前字符串的每一个字符,将其 ASCII 码减去 'a'
的 ASCII 码的下标的计数器上计数
1 2 3 4 5
| for (let j = 0; j < strLen; j++) { counter[str.charCodeAt(j) - aCode]++; }
|
使用计数器计算哈希值,按照 ${字母}${出现次数}...
的规则拼接,0 次的不处理
1 2 3 4 5 6 7 8 9 10
| let hashCode = '';
for (let j = 0; j < 26; j++) { if (counter[j]) { hashCode += String.fromCharCode(aCode + j) + counter[j]; } }
|
2. 哈希表处理
如果哈希表上哈希值的位置已有数组,直接把当前字符推入,否则在该位置上新建数组,同时把该数组推入结果
1 2 3 4 5 6 7 8
| if (hashMap.has(hashCode)) hashMap.get(hashCode).push(str);
else { const arr = [str]; result.push(arr); hashMap.set(hashCode, arr); }
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
var groupAnagrams = function (strs) { const result = []; const hashMap = new Map(); const aCode = 'a'.charCodeAt(0); for (let i = 0; i < strs.length; i++) { const str = strs[i]; const strLen = str.length; const counter = new Array(26); for (let j = 0; j < counter.length; j++) { counter[j] = 0; } for (let j = 0; j < strLen; j++) { counter[str.charCodeAt(j) - aCode]++; } let hashCode = ''; for (let j = 0; j < 26; j++) { if (counter[j]) { hashCode += String.fromCharCode(aCode + j) + counter[j]; } } if (hashMap.has(hashCode)) hashMap.get(hashCode).push(str); else { const arr = [str]; result.push(arr); hashMap.set(hashCode, arr); } } return result; };
|