7-12 LeetCode 49 字母异位词分组
题目
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例1:
输入: strs =
["eat", "tea", "tan", "ate", "nat", "bat"]
输出:[["bat"],["nat","tan"],["ate","eat","tea"]]
示例2:
输入: strs =
[""]
输出:
[[""]]
示例 3:
输入: strs =
["a"]
输出:
[["a"]]
思路(排序,遍历)
另起一个数组sorted里面存放的字符串为strs中每一个字符串经过排序过后的结果。
original = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 经过排序后
sorted = [“aet”, “aet”, “ant”, “aet”, “ant”, “abt”]
构造结构体 dict
用于存放每一组 "eat" : "aet" ...... "bat" : "abt"
达到类似 key - value 的效果
创建数组Pairs
用于存放每一对 key - value,数组Pairs
为 [{"eat" : "aet"} ...... {"bat" : "abt"}]
此时在对数组Pairs
进行排序,根据sorted
字符串进行升序排序
遍历数组Pairs
访问每一个排序后的字符串及Pairs[i].sorted
:
- 当遇到第一个元素 或者 当前排序后的字符串
Pairs[i].sorted
与 前一个字符串不相等时Pairs[i - 1].sorted
不相等时,新建一个数组,将原字符串Pairs[i].original
存放进入新建数组中,并且更新ret
数组长度,新建数组长度设为1。 - 当前排序后的字符串
Pairs[i].sorted
与 前一个字符串不相等时Pairs[i - 1].sorted
相等时,Pairs[i].sorted
对应的Pairs[i].original
存放进入前一步已创造的数组当中,并且更新对应数组的长度。
最后对结果ret
进行返回即可。
详细
Pairs数组建立好后,Pairs.orinal 指向的是strs , Pairs.sorted 则是对应的字符串内容排序后
遍历开始时, i = 0
时需要创建一个子数组用于存放字符串Pairs[i].orinal
当 i = 1
时 “tea” != “aet” 创建新的子数组用于存放字符串
当 i = 2时,Pairs[i].sorted 和 Pairs[i - i].sorted
相等,是字母异位词,将字符串存放于ret[i]
数组中
后续情况和上述两种相似,当遍历完Pairs
时,得到结果ret
返回
代码实现
struct dict{
char* original;
char* sorted;
};
int cmpChar(const void* a,const void* b){
return *(const char*)a - *(const char*)b;
}
int cmpPairs(const void* a,const void* b){
struct dict* tmp_a = (struct dict*)a;
struct dict* tmp_b = (struct dict*)b;
return strcmp(tmp_a->sorted,tmp_b->sorted);
}
char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes){
//判断给定数组是否为空
if(NULL == strs || 0 == strsSize){
return NULL;
}
//初始化Pairs数组,并为其分配内存空间
//Pairs数组每个元素是struct dict类型,数组长度和strs数组长度相同
struct dict* Pairs = malloc(sizeof(struct dict) * strsSize);
//遍历并拷贝strs中的每个字符串,并对每个字符串内部进行排序
for(int i = 0; i < strsSize; i++){
//为字符串分配空间,用于保存strs数组中每个字符串
char* sorted = malloc(sizeof(char) * (strlen(strs[i]) + 1));
//将strs[i] 拷贝到 sorted ( strs[i] ==> "bat" , sorted == "bat")
strcpy(sorted,strs[i]);
//排序函数,对strs中每个字符串内部进行排序 数组首地址,数组长度,数组元素所占空间大小,比较函数
qsort(sorted,strlen(strs[i]),sizeof(char),cmpChar);
//将字符串首地址赋值
Pairs[i].original = strs[i];
Pairs[i].sorted = sorted;
}
//对Pairs数组进行排序
qsort(Pairs,strsSize,sizeof(struct dict),cmpPairs);
//为返回结果ret分配内存空间
char*** ret = malloc(sizeof(char **) * strsSize);
//为保存子数组长度的数组分配内存空间
*returnColumnSizes = malloc(sizeof(int) * strsSize);
//对返回的ret数组长度初始化
*returnSize = 0;
//遍历Pairs
for(int i = 0; i < strsSize; i++){
//当为第一个字符串 或者 当前字符串和上一个字符串不相等时,需要开辟新数组
if(0 == i || strcmp(Pairs[i].sorted,Pairs[i - 1].sorted) != 0 ){
//记录当前添加元素应该添加到的下标位置
int lastIndex = (*returnSize);
//为数组分配内存空间
ret[lastIndex] = malloc(sizeof(char *));
//将字符串首地址赋值给新开辟数组的第一个元素
ret[lastIndex][0] = Pairs[i].original;
//ret数组长度增加
(*returnSize)++;
//记录新开辟数组的长度
(*returnColumnSizes)[lastIndex] = 1;
}else{ //当前字符串和上一个字符串相等时,无需开辟新数组,将当前字符串添加到 ret 最后一个子数组后
//ret 最后一个子数组的下标 (*returnSize)表示长度,下标为长度 - 1
int lastIndex = (*returnSize) - 1;
//获取该字符串要添加到子数组的下标 (是当前子数组未添加元素的长度)
int lastSubIndex = (*returnColumnSizes)[lastIndex];
//对 ret 最后一个子数组扩容
ret[lastIndex] = realloc(ret[lastIndex],sizeof(char *) *(lastSubIndex + 1));
//将字符串首地址赋值
ret[lastIndex][lastSubIndex] = Pairs[i].original;
//最后一个子数组长度 + 1
(*returnColumnSizes)[lastIndex] = lastSubIndex + 1;
}
}
return ret;
}