【C语言刷题】力扣49 字母异位词分组

目录

解法1:哈希表(排序后的字符串作为键)


解法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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值