目录
解法1:哈希表(排序后的字符串作为键)
/**********************************************************************/
/* StrArr */
/**********************************************************************/
typedef struct str_arr {
size_t dySize;
char** arr;
size_t strNum;
} str_arr_t;
void str_arr_init(str_arr_t* pStrArr, size_t size)
{
pStrArr->arr = malloc(sizeof(*pStrArr->arr) * size);
pStrArr->dySize = size;
pStrArr->strNum = 0;
}
void str_arr_insert(str_arr_t* pStrArr, const char* str)
{
if (pStrArr->strNum >= pStrArr->dySize)
{
pStrArr->dySize <<= 1;
pStrArr->arr = realloc(pStrArr->arr, sizeof(*pStrArr->arr) * pStrArr->dySize);
}
pStrArr->arr[pStrArr->strNum] = malloc(sizeof(**pStrArr->arr) * (strlen(str) + 1));
strcpy(pStrArr->arr[pStrArr->strNum], str);
pStrArr->strNum++;
}
/**********************************************************************/
/* HashMap */
/**********************************************************************/
typedef char* pair_key_t;
typedef str_arr_t pair_val_t;
typedef struct pair {
pair_key_t key;
pair_val_t val;
} pair_t;
typedef struct pair_node {
pair_t pair;
struct pair_node* pNext;
} pair_node_t;
typedef struct hash_bucket {
pair_node_t* pHead;
} hash_bucket_t;
typedef struct hash_map {
hash_bucket_t* table;
size_t tableSize;
} hash_map_t;
hash_map_t* hash_map_alloc(size_t size)
{
hash_map_t* pHashMap = malloc(sizeof(*pHashMap));
pHashMap->table = calloc(size, sizeof(*pHashMap->table));
pHashMap->tableSize = size;
return pHashMap;
}
uint64_t _hash_code(pair_key_t key)
{
uint64_t hashCode = 0;
for (size_t i = 0; i < strlen(key); i++)
hashCode += key[i] * (uint64_t)pow(31, i);
return hashCode;
}
inline size_t _hash(size_t tableSize, uint64_t hashCode)
{
return hashCode % tableSize;
}
bool hash_map_search(hash_map_t* pHashMap, pair_key_t key, pair_val_t* pVal)
{
// 获取可能存放当前结点的哈希桶
size_t addr = _hash(pHashMap->tableSize, _hash_code(key));
pair_node_t* pNode = pHashMap->table[addr].pHead;
// 从哈希桶中搜索当前键
while (pNode)
{
if (!strcmp(pNode->pair.key, key))
{
if (pVal)
*pVal = pNode->pair.val;
return true;
}
pNode = pNode->pNext;
}
return false;
}
void hash_map_insert(hash_map_t* pHashMap, const pair_t* pPair)
{
// 防止重复插入
if (hash_map_search(pHashMap, pPair->key, NULL))
return;
// 动态生成结点
pair_node_t* pNode = malloc(sizeof(*pNode));
pNode->pair.key = malloc(sizeof(*pNode->pair.key) * (strlen(pPair->key) + 1));
strcpy(pNode->pair.key, pPair->key);
pNode->pair.val = pPair->val;
// 结点放入对应的哈希桶(键值对链表头插)
size_t addr = _hash(pHashMap->tableSize, _hash_code(pPair->key));
pNode->pNext = pHashMap->table[addr].pHead;
pHashMap->table[addr].pHead = pNode;
}
void hash_map_update(hash_map_t* pHashMap, const pair_t* pPair)
{
// 获取可能存放当前结点的哈希桶
size_t addr = _hash(pHashMap->tableSize, _hash_code(pPair->key));
pair_node_t* pNode = pHashMap->table[addr].pHead;
// 从哈希桶中搜索当前键并更新键对应的值
while (pNode)
{
if (!strcmp(pNode->pair.key, pPair->key))
{
pNode->pair.val = pPair->val;
return;
}
pNode = pNode->pNext;
}
}
typedef void (*hash_map_foreach_callback_t)(pair_node_t*, void*);
void hash_map_foreach(hash_map_t* pHashMap, hash_map_foreach_callback_t func, void* pUser)
{
for (size_t i = 0; i < pHashMap->tableSize; i++)
{
pair_node_t* pNode = pHashMap->table[i].pHead;
while (pNode)
{
func(pNode, pUser);
pNode = pNode->pNext;
}
}
}
void hash_map_free(hash_map_t* pHashMap)
{
for (size_t i = 0; i < pHashMap->tableSize; i++)
{
pair_node_t* pNode = pHashMap->table[i].pHead;
while (pNode)
{
pair_node_t* pFreeNode = pNode;
pNode = pNode->pNext;
free(pFreeNode->pair.key);
free(pFreeNode);
}
}
free(pHashMap->table);
free(pHashMap);
}
/**********************************************************************/
/* Main */
/**********************************************************************/
typedef struct user {
size_t dySize;
char*** strArrs;
int* strNumArr;
int strArrNum;
} user_t;
int compare(const void* a, const void* b)
{
return *(char*)a - *(char*)b;
}
void hash_map_foreach_callback(pair_node_t* pPairNode, void* pUser)
{
user_t* ptrUser = pUser;
if (ptrUser->strArrNum >= ptrUser->dySize)
{
ptrUser->dySize <<= 1;
ptrUser->strArrs =
realloc(ptrUser->strArrs, sizeof(*ptrUser->strArrs) * ptrUser->dySize);
ptrUser->strNumArr =
realloc(ptrUser->strNumArr, sizeof(*ptrUser->strNumArr) * ptrUser->dySize);
}
ptrUser->strArrs[ptrUser->strArrNum] = pPairNode->pair.val.arr;
ptrUser->strNumArr[ptrUser->strArrNum] = pPairNode->pair.val.strNum;
ptrUser->strArrNum++;
}
char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes)
{
hash_map_t* pHashMap = hash_map_alloc(512);
for (int i = 0; i < strsSize; i++)
{
// 将字符串进行排序
char str[101];
strcpy(str, strs[i]);
qsort(str, strlen(str), sizeof(*str), compare);
// 使用排序后的字符串作为键,组合字母异位词
str_arr_t strArr;
if (hash_map_search(pHashMap, str, &strArr))
{
str_arr_insert(&strArr, strs[i]);
hash_map_update(pHashMap, &(pair_t){str, strArr});
}
else
{
str_arr_init(&strArr, 16);
str_arr_insert(&strArr, strs[i]);
hash_map_insert(pHashMap, &(pair_t){str, strArr});
}
}
user_t user = {
.dySize = 16,
.strArrs = malloc(sizeof(*user.strArrs) * user.dySize),
.strNumArr = malloc(sizeof(*user.strNumArr) * user.dySize),
.strArrNum = 0,
};
hash_map_foreach(pHashMap, hash_map_foreach_callback, &user);
hash_map_free(pHashMap);
*returnSize = user.strArrNum;
*returnColumnSizes = user.strNumArr;
return user.strArrs;
}