题目链接:https://leetcode-cn.com/problems/group-anagrams/
题目:给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
分析:与前两道题同样,本题采用C语言的uthash库,这一道题与36. 有效的数独和136. 只出现一次的数字的 区别在于key是字符串,因此我们对uthash的接口重新进行了封装,本次的封装的key可以是结构体,同样可以在前两道题使用,这样的封装更具有拓展性。本地还用到了字符串排序与拷贝接口。
重新封装的接口如下,我们将key和val都作为结构体类型便于扩展,print接口需要根据需求自行修改:
typedef struct {
int a;
char b[20];
} uthash_key_s;
typedef struct {
int c;
char d;
} uthash_val_s;
typedef struct {
uthash_key_s key;
uthash_val_s val;
UT_hash_handle hh;
} uthash_map_s;
uthash_map_s* uthash_create(void)
{
uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
s = NULL;
return s;
}
void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
if (s == NULL) {
s = (uthash_map_s *)malloc(sizeof(*s));
s->key = key;
HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
}
s->val = val;
}
uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
return s;
}
void uthash_delete(uthash_map_s **hash, uthash_key_s key)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
if (s != NULL) {
HASH_DEL(*hash, s);
free(s);
}
}
void uthash_delete_all(uthash_map_s **hash)
{
uthash_map_s *s, *tmp;
HASH_ITER(hh, *hash, s, tmp) {
HASH_DEL(*hash, s);
free(s);
}
}
void uthash_print(uthash_map_s **hash)
{
uthash_map_s *s;
for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) {
printf("key %d: val %d\n", s->key.a, s->val.c); // 自行根据数据结构修改
}
}
unsigned int uthash_get_count(uthash_map_s **hash)
{
return HASH_COUNT(*hash);
}
void uthash_test(void)
{
// create
uthash_map_s *hash = uthash_create();
// add
uthash_key_s key;
key.a = 1;
strcpy(key.b, "aaa");
uthash_val_s val;
val.c = 10;
val.d = 'h';
uthash_add(&hash, key, val);
uthash_print(&hash);
printf("\n");
key.a = 2;
strcpy(key.b, "bbb");
val.c = 11;
val.d = 'j';
uthash_add(&hash, key, val);
uthash_print(&hash);
printf("\n");
// find
uthash_key_s key2;
key2.a = 1;
strcpy(key2.b, "aaa");
if (uthash_find(&hash, key2) != NULL) {
printf("find key\n");
}
// count
printf("hash map num:%d\n", uthash_get_count(&hash));
// delete
uthash_delete(&hash, key2);
uthash_print(&hash);
printf("\n");
// delete all
uthash_delete_all(&hash);
printf("hash map num:%d\n", uthash_get_count(&hash));
}
对以上的通用结构再次改造,以适应本题:
#define CHAR_NUM 1000
typedef struct {
char name[CHAR_NUM];
} uthash_key_s;
typedef struct {
int index;
} uthash_val_s;
typedef struct {
uthash_key_s key;
uthash_val_s val;
UT_hash_handle hh;
} uthash_map_s;
uthash_map_s* uthash_create(void)
{
uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
s = NULL;
return s;
}
void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
if (s == NULL) {
s = (uthash_map_s *)malloc(sizeof(*s));
s->key = key;
HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
}
s->val = val;
}
uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
return s;
}
void uthash_delete(uthash_map_s **hash, uthash_key_s key)
{
uthash_map_s *s;
HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
if (s != NULL) {
HASH_DEL(*hash, s);
free(s);
}
}
void uthash_delete_all(uthash_map_s **hash)
{
uthash_map_s *s, *tmp;
HASH_ITER(hh, *hash, s, tmp) {
HASH_DEL(*hash, s);
free(s);
}
}
void uthash_print(uthash_map_s **hash)
{
uthash_map_s *s;
for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) {
printf("key %s: val %d\n", s->key.name, s->val.index); // 自行根据数据结构修改
}
}
unsigned int uthash_get_count(uthash_map_s **hash)
{
return HASH_COUNT(*hash);
}
/**
* 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().
*/
int cmp(const char* a, const char* b)
{
return *a - *b;
}
char *** groupAnagrams(char ** strs, int strsSize, int* returnSize, int** returnColumnSizes){
if (strsSize <= 0 || strs == NULL) {
return NULL;
}
char ***res = (char***)malloc(sizeof(char**) * strsSize);
for (int i = 0; i < strsSize; i++) {
res[i] = (char**)malloc(sizeof(char*) * strsSize);
}
*returnSize = 0;
*returnColumnSizes = (int*)malloc(sizeof(int*) * strsSize);
memset(*returnColumnSizes, 0, sizeof(int*) * strsSize);
uthash_map_s *hash = uthash_create();
uthash_key_s key;
uthash_val_s val;
uthash_map_s *hash_tmp;
val.index = 0;
int row, col;
for (int i = 0; i < strsSize; i++) {
memset(key.name, 0, CHAR_NUM);
strcpy(key.name, strs[i]);
qsort(key.name, strlen(key.name), sizeof(char), cmp);
hash_tmp = uthash_find(&hash, key);
if(hash_tmp == NULL) {
row = val.index;
col = 0;
uthash_add(&hash, key, val);
val.index++;
} else {
row = hash_tmp->val.index;
col = *(*returnColumnSizes + row);
}
res[row][col] = strs[i];
*(*returnColumnSizes + row) += 1;
}
*returnSize = val.index;
//uthash_print(&hash);
uthash_delete_all(&hash);
return res;
}
执行用时 :152 ms, 在所有 C 提交中击败了42.73%的用户
内存消耗 :269.1 MB, 在所有 C 提交中击败了13.79%的用户