给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
示例 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] 仅包含小写字母
思路:
记录每个单词各个字母出现的次数,两个单词之间若是每个字母出现的次数都想同,则说明两个单词异位,依据这个思路找出所有的异位单词。
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
char *** groupAnagrams(char ** strs, int strsSize, int* returnSize, int** returnColumnSizes){
if(strsSize == 0){
*returnSize = 0;
return NULL;
}
int str_count[10100][26] = {0}; //用来存储每个单词个个字母出现的次数
int book[10100] = {0}; //用来标记同组单词
int flags[10100] = {0}; //用来标记是否已经被加入到返回数组中
char ***ans;
ans = malloc(sizeof(char **) * 10010);
*returnColumnSizes = malloc(sizeof(int) * 10010);
*returnSize = 0;
//获取每个单词各个字母出现的次数
for(int i = 0; i < strsSize; i++){
for(int j = 0; j < strlen(strs[i]); j++){
str_count[i][strs[i][j] - 'a']++;
}
}
int k = 0;
int count = 0;
//双层循环,外城循环控制
for(int i = 0; i < strsSize; i++){
if(flags[i])
continue;
flags[i] = 1;
memset(book, 0, sizeof(book));
count = 0;
book[count++] = i;
for(int j = i + 1; j < strsSize; j++){
if(flags[j])
continue;
//判断单词是否异位
for(k = 0; k < 26; k++){
if(str_count[i][k] != str_count[j][k])
break;
}
//若是异位则标记
if(k == 26){
book[count++] = j;
flags[j] = 1;
}
}
*(ans + *returnSize) = malloc(sizeof(char *) * count);
//没有动态申请空间,直接使用单词的地址
for(k = 0; k < count; k++){
ans[*returnSize][k] = strs[book[k]];
}
(*returnColumnSizes)[*returnSize] = count;
(*returnSize) ++;
}
return ans;
}